brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.0 KiB · 1bec83b Raw
373 lines · cpp
1//===-- sanitizer_libc_test.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// Tests for sanitizer_libc.h.9//===----------------------------------------------------------------------===//10#include <algorithm>11#include <vector>12#include <stdio.h>13 14#include "sanitizer_common/sanitizer_common.h"15#include "sanitizer_common/sanitizer_file.h"16#include "sanitizer_common/sanitizer_libc.h"17#include "sanitizer_common/sanitizer_platform.h"18#include "gtest/gtest.h"19 20#if SANITIZER_WINDOWS21#define NOMINMAX22#include <windows.h>23#undef NOMINMAX24#endif25#if SANITIZER_POSIX26# include <sys/stat.h>27# include "sanitizer_common/sanitizer_posix.h"28#endif29 30using namespace __sanitizer;31 32// A regression test for internal_memmove() implementation.33TEST(SanitizerCommon, InternalMemmoveRegression) {34  char src[] = "Hello World";35  char *dest = src + 6;36  __sanitizer::internal_memmove(dest, src, 5);37  EXPECT_EQ(dest[0], src[0]);38  EXPECT_EQ(dest[4], src[4]);39}40 41TEST(SanitizerCommon, mem_is_zero) {42  size_t size = 128;43  char *x = new char[size];44  memset(x, 0, size);45  for (size_t pos = 0; pos < size; pos++) {46    x[pos] = 1;47    for (size_t beg = 0; beg < size; beg++) {48      for (size_t end = beg; end < size; end++) {49        // fprintf(stderr, "pos %zd beg %zd end %zd \n", pos, beg, end);50        if (beg <= pos && pos < end)51          EXPECT_FALSE(__sanitizer::mem_is_zero(x + beg, end - beg));52        else53          EXPECT_TRUE(__sanitizer::mem_is_zero(x + beg, end - beg));54      }55    }56    x[pos] = 0;57  }58  delete [] x;59}60 61struct stat_and_more {62  struct stat st;63  unsigned char z;64};65 66static void get_temp_dir(char *buf, size_t bufsize) {67#if SANITIZER_WINDOWS68  buf[0] = '\0';69  if (!::GetTempPathA(bufsize, buf))70    return;71#else72  const char *tmpdir = "/tmp";73#  if SANITIZER_ANDROID74  tmpdir = GetEnv("TMPDIR");75#  endif76  internal_snprintf(buf, bufsize, "%s", tmpdir);77#endif78}79 80static void temp_file_name(char *buf, size_t bufsize, const char *prefix) {81#if SANITIZER_WINDOWS82  buf[0] = '\0';83  char tmp_dir[MAX_PATH];84  if (!::GetTempPathA(MAX_PATH, tmp_dir))85    return;86  // GetTempFileNameA needs a MAX_PATH buffer.87  char tmp_path[MAX_PATH];88  if (!::GetTempFileNameA(tmp_dir, prefix, 0, tmp_path))89    return;90  internal_strncpy(buf, tmp_path, bufsize);91#else92  const char *tmpdir = "/tmp";93#if SANITIZER_ANDROID94  tmpdir = GetEnv("TMPDIR");95#endif96  internal_snprintf(buf, bufsize, "%s/%sXXXXXX", tmpdir, prefix);97  ASSERT_TRUE(mkstemp(buf));98#endif99}100 101static void Unlink(const char *path) {102#if SANITIZER_WINDOWS103  // No sanitizer needs to delete a file on Windows yet. If we ever do, we can104  // add a portable wrapper and test it from here.105  ::DeleteFileA(&path[0]);106#else107  internal_unlink(path);108#endif109}110 111TEST(SanitizerCommon, FileOps) {112  const char *str1 = "qwerty";113  uptr len1 = internal_strlen(str1);114  const char *str2 = "zxcv";115  uptr len2 = internal_strlen(str2);116 117  char tmpfile[128];118  temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp.");119  fd_t fd = OpenFile(tmpfile, WrOnly);120  ASSERT_NE(fd, kInvalidFd);121  ASSERT_TRUE(WriteToFile(fd, "A", 1));122  CloseFile(fd);123 124  fd = OpenFile(tmpfile, WrOnly);125  ASSERT_NE(fd, kInvalidFd);126#if SANITIZER_POSIX && !SANITIZER_APPLE127  EXPECT_EQ(internal_lseek(fd, 0, SEEK_END), 0u);128#endif129  uptr bytes_written = 0;130  EXPECT_TRUE(WriteToFile(fd, str1, len1, &bytes_written));131  EXPECT_EQ(len1, bytes_written);132  EXPECT_TRUE(WriteToFile(fd, str2, len2, &bytes_written));133  EXPECT_EQ(len2, bytes_written);134  CloseFile(fd);135 136  EXPECT_TRUE(FileExists(tmpfile));137 138  fd = OpenFile(tmpfile, RdOnly);139  ASSERT_NE(fd, kInvalidFd);140 141#if SANITIZER_POSIX142  // The stat wrappers are posix-only.143  uptr fsize = internal_filesize(fd);144  EXPECT_EQ(len1 + len2, fsize);145 146  struct stat st1, st2, st3;147  EXPECT_EQ(0u, internal_stat(tmpfile, &st1));148  EXPECT_EQ(0u, internal_lstat(tmpfile, &st2));149  EXPECT_EQ(0u, internal_fstat(fd, &st3));150  EXPECT_EQ(fsize, (uptr)st3.st_size);151 152  // Verify that internal_fstat does not write beyond the end of the supplied153  // buffer.154  struct stat_and_more sam;155  memset(&sam, 0xAB, sizeof(sam));156  EXPECT_EQ(0u, internal_fstat(fd, &sam.st));157  EXPECT_EQ(0xAB, sam.z);158  EXPECT_NE(0xAB, sam.st.st_size);159  EXPECT_NE(0, sam.st.st_size);160#endif161 162  char buf[64] = {};163  uptr bytes_read = 0;164  EXPECT_TRUE(ReadFromFile(fd, buf, len1, &bytes_read));165  EXPECT_EQ(len1, bytes_read);166  EXPECT_EQ(0, internal_memcmp(buf, str1, len1));167  EXPECT_EQ((char)0, buf[len1 + 1]);168  internal_memset(buf, 0, len1);169  EXPECT_TRUE(ReadFromFile(fd, buf, len2, &bytes_read));170  EXPECT_EQ(len2, bytes_read);171  EXPECT_EQ(0, internal_memcmp(buf, str2, len2));172  CloseFile(fd);173 174  Unlink(tmpfile);175}176 177class SanitizerCommonFileTest : public ::testing::TestWithParam<uptr> {178  void SetUp() override {179    data_.resize(GetParam());180    std::generate(data_.begin(), data_.end(), [] { return rand() % 256; });181 182    temp_file_name(file_name_, sizeof(file_name_),183                   "sanitizer_common.ReadFile.tmp.");184 185    if (FILE *f = fopen(file_name_, "wb")) {186      if (!data_.empty())187        fwrite(data_.data(), data_.size(), 1, f);188      fclose(f);189    }190  }191 192  void TearDown() override { Unlink(file_name_); }193 194 protected:195  char file_name_[256];196  std::vector<char> data_;197};198 199TEST_P(SanitizerCommonFileTest, ReadFileToBuffer) {200  char *buff;201  uptr size;202  uptr len;203  EXPECT_TRUE(ReadFileToBuffer(file_name_, &buff, &len, &size));204  EXPECT_EQ(data_, std::vector<char>(buff, buff + size));205  UnmapOrDie(buff, len);206}207 208TEST_P(SanitizerCommonFileTest, ReadFileToBufferHalf) {209  char *buff;210  uptr size;211  uptr len;212  data_.resize(data_.size() / 2);213  EXPECT_TRUE(ReadFileToBuffer(file_name_, &buff, &len, &size, data_.size()));214  EXPECT_EQ(data_, std::vector<char>(buff, buff + size));215  UnmapOrDie(buff, len);216}217 218TEST_P(SanitizerCommonFileTest, ReadFileToVector) {219  InternalMmapVector<char> buff;220  EXPECT_TRUE(ReadFileToVector(file_name_, &buff));221  EXPECT_EQ(data_, std::vector<char>(buff.begin(), buff.end()));222}223 224TEST_P(SanitizerCommonFileTest, ReadFileToVectorHalf) {225  InternalMmapVector<char> buff;226  data_.resize(data_.size() / 2);227  EXPECT_TRUE(ReadFileToVector(file_name_, &buff, data_.size()));228  EXPECT_EQ(data_, std::vector<char>(buff.begin(), buff.end()));229}230 231INSTANTIATE_TEST_SUITE_P(FileSizes, SanitizerCommonFileTest,232                         ::testing::Values(0, 1, 7, 13, 32, 4096, 4097, 1048575,233                                           1048576, 1048577));234 235static const size_t kStrlcpyBufSize = 8;236void test_internal_strlcpy(char *dbuf, const char *sbuf) {237  uptr retval = 0;238  retval = internal_strlcpy(dbuf, sbuf, kStrlcpyBufSize);239  EXPECT_EQ(internal_strncmp(dbuf, sbuf, kStrlcpyBufSize - 1), 0);240  EXPECT_EQ(internal_strlen(dbuf),241            std::min(internal_strlen(sbuf), (uptr)(kStrlcpyBufSize - 1)));242  EXPECT_EQ(retval, internal_strlen(sbuf));243 244  // Test with shorter maxlen.245  uptr maxlen = 2;246  if (internal_strlen(sbuf) > maxlen) {247    retval = internal_strlcpy(dbuf, sbuf, maxlen);248    EXPECT_EQ(internal_strncmp(dbuf, sbuf, maxlen - 1), 0);249    EXPECT_EQ(internal_strlen(dbuf), maxlen - 1);250  }251}252 253TEST(SanitizerCommon, InternalStrFunctions) {254  const char *haystack = "haystack";255  EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y'));256  EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y'));257  EXPECT_EQ(0, internal_strchr(haystack, 'z'));258  EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z'));259 260  char dbuf[kStrlcpyBufSize] = {};261  const char *samesizestr = "1234567";262  const char *shortstr = "123";263  const char *longerstr = "123456789";264 265  // Test internal_strlcpy.266  internal_strlcpy(dbuf, shortstr, 0);267  EXPECT_EQ(dbuf[0], 0);268  EXPECT_EQ(dbuf[0], 0);269  test_internal_strlcpy(dbuf, samesizestr);270  test_internal_strlcpy(dbuf, shortstr);271  test_internal_strlcpy(dbuf, longerstr);272 273  // Test internal_strlcat.274  char dcatbuf[kStrlcpyBufSize] = {};275  uptr retval = 0;276  retval = internal_strlcat(dcatbuf, "aaa", 0);277  EXPECT_EQ(internal_strlen(dcatbuf), (uptr)0);278  EXPECT_EQ(retval, (uptr)3);279 280  retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);281  EXPECT_EQ(internal_strcmp(dcatbuf, "123"), 0);282  EXPECT_EQ(internal_strlen(dcatbuf), (uptr)3);283  EXPECT_EQ(retval, (uptr)3);284 285  retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);286  EXPECT_EQ(internal_strcmp(dcatbuf, "123123"), 0);287  EXPECT_EQ(internal_strlen(dcatbuf), (uptr)6);288  EXPECT_EQ(retval, (uptr)6);289 290  retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);291  EXPECT_EQ(internal_strcmp(dcatbuf, "1231231"), 0);292  EXPECT_EQ(internal_strlen(dcatbuf), (uptr)7);293  EXPECT_EQ(retval, (uptr)9);294}295 296TEST(SanitizerCommon, InternalWideStringFunctions) {297  const wchar_t *emptystr = L"";298  const wchar_t *samesizestr = L"1234567";299  const wchar_t *shortstr = L"123";300  const wchar_t *longerstr = L"123456789";301 302  ASSERT_EQ(internal_wcslen(emptystr), 0ul);303  ASSERT_EQ(internal_wcslen(samesizestr), 7ul);304  ASSERT_EQ(internal_wcslen(shortstr), 3ul);305  ASSERT_EQ(internal_wcslen(longerstr), 9ul);306 307  ASSERT_EQ(internal_wcsnlen(emptystr, 7), 0ul);308  ASSERT_EQ(internal_wcsnlen(samesizestr, 7), 7ul);309  ASSERT_EQ(internal_wcsnlen(shortstr, 7), 3ul);310  ASSERT_EQ(internal_wcsnlen(longerstr, 7), 7ul);311}312 313// FIXME: File manipulations are not yet supported on Windows314#if SANITIZER_POSIX && !SANITIZER_APPLE315TEST(SanitizerCommon, InternalMmapWithOffset) {316  char tmpfile[128];317  temp_file_name(tmpfile, sizeof(tmpfile),318                 "sanitizer_common.internalmmapwithoffset.tmp.");319  fd_t fd = OpenFile(tmpfile, RdWr);320  ASSERT_NE(fd, kInvalidFd);321 322  uptr page_size = GetPageSizeCached();323  uptr res = internal_ftruncate(fd, page_size * 2);324  ASSERT_FALSE(internal_iserror(res));325 326  res = internal_lseek(fd, page_size, SEEK_SET);327  ASSERT_FALSE(internal_iserror(res));328 329  res = internal_write(fd, "AB", 2);330  ASSERT_FALSE(internal_iserror(res));331 332  char *p = (char *)MapWritableFileToMemory(nullptr, page_size, fd, page_size);333  ASSERT_NE(nullptr, p);334 335  ASSERT_EQ('A', p[0]);336  ASSERT_EQ('B', p[1]);337 338  CloseFile(fd);339  UnmapOrDie(p, page_size);340  internal_unlink(tmpfile);341}342#endif343 344TEST(SanitizerCommon, ReportFile) {345  SpinMutex report_file_mu;346  ReportFile report_file = {&report_file_mu, kStderrFd, "", "", 0};347  char tmpfile[128];348  temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.reportfile.tmp.");349  report_file.SetReportPath(tmpfile);350  const char *path = report_file.GetReportPath();351  EXPECT_EQ(internal_strncmp(tmpfile, path, strlen(tmpfile)), 0);352  // This will close tmpfile.353  report_file.SetReportPath("stderr");354  Unlink(tmpfile);355  Unlink(path);356}357 358TEST(SanitizerCommon, FileExists) {359  char tmpfile[128];360  temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileexists.tmp.");361  fd_t fd = OpenFile(tmpfile, WrOnly);362  ASSERT_NE(fd, kInvalidFd);363  EXPECT_TRUE(FileExists(tmpfile));364  CloseFile(fd);365  Unlink(tmpfile);366}367 368TEST(SanitizerCommon, DirExists) {369  char tmpdir[128];370  get_temp_dir(tmpdir, sizeof(tmpdir));371  EXPECT_TRUE(DirExists(tmpdir));372}373