Home | History | Annotate | Line # | Download | only in tests
      1 //===-- sanitizer_libc_test.cc --------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 // Tests for sanitizer_libc.h.
     10 //===----------------------------------------------------------------------===//
     11 #include <algorithm>
     12 #include <fstream>
     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_WINDOWS
     21 #define NOMINMAX
     22 #include <windows.h>
     23 #undef NOMINMAX
     24 #endif
     25 #if SANITIZER_POSIX
     26 # include <sys/stat.h>
     27 # include "sanitizer_common/sanitizer_posix.h"
     28 #endif
     29 
     30 using namespace __sanitizer;
     31 
     32 // A regression test for internal_memmove() implementation.
     33 TEST(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 
     41 TEST(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         else
     53           EXPECT_TRUE(__sanitizer::mem_is_zero(x + beg, end - beg));
     54       }
     55     }
     56     x[pos] = 0;
     57   }
     58   delete [] x;
     59 }
     60 
     61 struct stat_and_more {
     62   struct stat st;
     63   unsigned char z;
     64 };
     65 
     66 static void temp_file_name(char *buf, size_t bufsize, const char *prefix) {
     67 #if SANITIZER_WINDOWS
     68   buf[0] = '\0';
     69   char tmp_dir[MAX_PATH];
     70   if (!::GetTempPathA(MAX_PATH, tmp_dir))
     71     return;
     72   // GetTempFileNameA needs a MAX_PATH buffer.
     73   char tmp_path[MAX_PATH];
     74   if (!::GetTempFileNameA(tmp_dir, prefix, 0, tmp_path))
     75     return;
     76   internal_strncpy(buf, tmp_path, bufsize);
     77 #else
     78   const char *tmpdir = "/tmp";
     79 #if SANITIZER_ANDROID
     80   // I don't know a way to query temp directory location on Android without
     81   // going through Java interfaces. The code below is not ideal, but should
     82   // work. May require "adb root", but it is needed for almost any use of ASan
     83   // on Android already.
     84   tmpdir = GetEnv("EXTERNAL_STORAGE");
     85 #endif
     86   internal_snprintf(buf, bufsize, "%s/%sXXXXXX", tmpdir, prefix);
     87   ASSERT_TRUE(mkstemp(buf));
     88 #endif
     89 }
     90 
     91 static void Unlink(const char *path) {
     92 #if SANITIZER_WINDOWS
     93   // No sanitizer needs to delete a file on Windows yet. If we ever do, we can
     94   // add a portable wrapper and test it from here.
     95   ::DeleteFileA(&path[0]);
     96 #else
     97   internal_unlink(path);
     98 #endif
     99 }
    100 
    101 TEST(SanitizerCommon, FileOps) {
    102   const char *str1 = "qwerty";
    103   uptr len1 = internal_strlen(str1);
    104   const char *str2 = "zxcv";
    105   uptr len2 = internal_strlen(str2);
    106 
    107   char tmpfile[128];
    108   temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp.");
    109   fd_t fd = OpenFile(tmpfile, WrOnly);
    110   ASSERT_NE(fd, kInvalidFd);
    111   ASSERT_TRUE(WriteToFile(fd, "A", 1));
    112   CloseFile(fd);
    113 
    114   fd = OpenFile(tmpfile, WrOnly);
    115   ASSERT_NE(fd, kInvalidFd);
    116 #if SANITIZER_POSIX && !SANITIZER_MAC
    117   EXPECT_EQ(internal_lseek(fd, 0, SEEK_END), 0u);
    118 #endif
    119   uptr bytes_written = 0;
    120   EXPECT_TRUE(WriteToFile(fd, str1, len1, &bytes_written));
    121   EXPECT_EQ(len1, bytes_written);
    122   EXPECT_TRUE(WriteToFile(fd, str2, len2, &bytes_written));
    123   EXPECT_EQ(len2, bytes_written);
    124   CloseFile(fd);
    125 
    126   EXPECT_TRUE(FileExists(tmpfile));
    127 
    128   fd = OpenFile(tmpfile, RdOnly);
    129   ASSERT_NE(fd, kInvalidFd);
    130 
    131 #if SANITIZER_POSIX
    132   // The stat wrappers are posix-only.
    133   uptr fsize = internal_filesize(fd);
    134   EXPECT_EQ(len1 + len2, fsize);
    135 
    136   struct stat st1, st2, st3;
    137   EXPECT_EQ(0u, internal_stat(tmpfile, &st1));
    138   EXPECT_EQ(0u, internal_lstat(tmpfile, &st2));
    139   EXPECT_EQ(0u, internal_fstat(fd, &st3));
    140   EXPECT_EQ(fsize, (uptr)st3.st_size);
    141 
    142   // Verify that internal_fstat does not write beyond the end of the supplied
    143   // buffer.
    144   struct stat_and_more sam;
    145   memset(&sam, 0xAB, sizeof(sam));
    146   EXPECT_EQ(0u, internal_fstat(fd, &sam.st));
    147   EXPECT_EQ(0xAB, sam.z);
    148   EXPECT_NE(0xAB, sam.st.st_size);
    149   EXPECT_NE(0, sam.st.st_size);
    150 #endif
    151 
    152   char buf[64] = {};
    153   uptr bytes_read = 0;
    154   EXPECT_TRUE(ReadFromFile(fd, buf, len1, &bytes_read));
    155   EXPECT_EQ(len1, bytes_read);
    156   EXPECT_EQ(0, internal_memcmp(buf, str1, len1));
    157   EXPECT_EQ((char)0, buf[len1 + 1]);
    158   internal_memset(buf, 0, len1);
    159   EXPECT_TRUE(ReadFromFile(fd, buf, len2, &bytes_read));
    160   EXPECT_EQ(len2, bytes_read);
    161   EXPECT_EQ(0, internal_memcmp(buf, str2, len2));
    162   CloseFile(fd);
    163 
    164   Unlink(tmpfile);
    165 }
    166 
    167 class SanitizerCommonFileTest : public ::testing::TestWithParam<uptr> {
    168   void SetUp() override {
    169     data_.resize(GetParam());
    170     std::generate(data_.begin(), data_.end(), [] {
    171       return rand() % 256;  // NOLINT
    172     });
    173 
    174     temp_file_name(file_name_, sizeof(file_name_),
    175                    "sanitizer_common.ReadFile.tmp.");
    176 
    177     std::ofstream f(file_name_, std::ios::out | std::ios::binary);
    178     if (!data_.empty())
    179       f.write(data_.data(), data_.size());
    180   }
    181 
    182   void TearDown() override { Unlink(file_name_); }
    183 
    184  protected:
    185   char file_name_[256];
    186   std::vector<char> data_;
    187 };
    188 
    189 TEST_P(SanitizerCommonFileTest, ReadFileToBuffer) {
    190   char *buff;
    191   uptr size;
    192   uptr len;
    193   EXPECT_TRUE(ReadFileToBuffer(file_name_, &buff, &len, &size));
    194   EXPECT_EQ(data_, std::vector<char>(buff, buff + size));
    195   UnmapOrDie(buff, len);
    196 }
    197 
    198 TEST_P(SanitizerCommonFileTest, ReadFileToBufferHalf) {
    199   char *buff;
    200   uptr size;
    201   uptr len;
    202   data_.resize(data_.size() / 2);
    203   EXPECT_TRUE(ReadFileToBuffer(file_name_, &buff, &len, &size, data_.size()));
    204   EXPECT_EQ(data_, std::vector<char>(buff, buff + size));
    205   UnmapOrDie(buff, len);
    206 }
    207 
    208 TEST_P(SanitizerCommonFileTest, ReadFileToVector) {
    209   InternalMmapVector<char> buff;
    210   EXPECT_TRUE(ReadFileToVector(file_name_, &buff));
    211   EXPECT_EQ(data_, std::vector<char>(buff.begin(), buff.end()));
    212 }
    213 
    214 TEST_P(SanitizerCommonFileTest, ReadFileToVectorHalf) {
    215   InternalMmapVector<char> buff;
    216   data_.resize(data_.size() / 2);
    217   EXPECT_TRUE(ReadFileToVector(file_name_, &buff, data_.size()));
    218   EXPECT_EQ(data_, std::vector<char>(buff.begin(), buff.end()));
    219 }
    220 
    221 INSTANTIATE_TEST_CASE_P(FileSizes, SanitizerCommonFileTest,
    222                         ::testing::Values(0, 1, 7, 13, 32, 4096, 4097, 1048575,
    223                                           1048576, 1048577));
    224 
    225 static const size_t kStrlcpyBufSize = 8;
    226 void test_internal_strlcpy(char *dbuf, const char *sbuf) {
    227   uptr retval = 0;
    228   retval = internal_strlcpy(dbuf, sbuf, kStrlcpyBufSize);
    229   EXPECT_EQ(internal_strncmp(dbuf, sbuf, kStrlcpyBufSize - 1), 0);
    230   EXPECT_EQ(internal_strlen(dbuf),
    231             std::min(internal_strlen(sbuf), (uptr)(kStrlcpyBufSize - 1)));
    232   EXPECT_EQ(retval, internal_strlen(sbuf));
    233 
    234   // Test with shorter maxlen.
    235   uptr maxlen = 2;
    236   if (internal_strlen(sbuf) > maxlen) {
    237     retval = internal_strlcpy(dbuf, sbuf, maxlen);
    238     EXPECT_EQ(internal_strncmp(dbuf, sbuf, maxlen - 1), 0);
    239     EXPECT_EQ(internal_strlen(dbuf), maxlen - 1);
    240   }
    241 }
    242 
    243 TEST(SanitizerCommon, InternalStrFunctions) {
    244   const char *haystack = "haystack";
    245   EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y'));
    246   EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y'));
    247   EXPECT_EQ(0, internal_strchr(haystack, 'z'));
    248   EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z'));
    249 
    250   char dbuf[kStrlcpyBufSize] = {};
    251   const char *samesizestr = "1234567";
    252   const char *shortstr = "123";
    253   const char *longerstr = "123456789";
    254 
    255   // Test internal_strlcpy.
    256   internal_strlcpy(dbuf, shortstr, 0);
    257   EXPECT_EQ(dbuf[0], 0);
    258   EXPECT_EQ(dbuf[0], 0);
    259   test_internal_strlcpy(dbuf, samesizestr);
    260   test_internal_strlcpy(dbuf, shortstr);
    261   test_internal_strlcpy(dbuf, longerstr);
    262 
    263   // Test internal_strlcat.
    264   char dcatbuf[kStrlcpyBufSize] = {};
    265   uptr retval = 0;
    266   retval = internal_strlcat(dcatbuf, "aaa", 0);
    267   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)0);
    268   EXPECT_EQ(retval, (uptr)3);
    269 
    270   retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
    271   EXPECT_EQ(internal_strcmp(dcatbuf, "123"), 0);
    272   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)3);
    273   EXPECT_EQ(retval, (uptr)3);
    274 
    275   retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
    276   EXPECT_EQ(internal_strcmp(dcatbuf, "123123"), 0);
    277   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)6);
    278   EXPECT_EQ(retval, (uptr)6);
    279 
    280   retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
    281   EXPECT_EQ(internal_strcmp(dcatbuf, "1231231"), 0);
    282   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)7);
    283   EXPECT_EQ(retval, (uptr)9);
    284 }
    285 
    286 // FIXME: File manipulations are not yet supported on Windows
    287 #if SANITIZER_POSIX && !SANITIZER_MAC
    288 TEST(SanitizerCommon, InternalMmapWithOffset) {
    289   char tmpfile[128];
    290   temp_file_name(tmpfile, sizeof(tmpfile),
    291                  "sanitizer_common.internalmmapwithoffset.tmp.");
    292   fd_t fd = OpenFile(tmpfile, RdWr);
    293   ASSERT_NE(fd, kInvalidFd);
    294 
    295   uptr page_size = GetPageSizeCached();
    296   uptr res = internal_ftruncate(fd, page_size * 2);
    297   ASSERT_FALSE(internal_iserror(res));
    298 
    299   res = internal_lseek(fd, page_size, SEEK_SET);
    300   ASSERT_FALSE(internal_iserror(res));
    301 
    302   res = internal_write(fd, "AB", 2);
    303   ASSERT_FALSE(internal_iserror(res));
    304 
    305   char *p = (char *)MapWritableFileToMemory(nullptr, page_size, fd, page_size);
    306   ASSERT_NE(nullptr, p);
    307 
    308   ASSERT_EQ('A', p[0]);
    309   ASSERT_EQ('B', p[1]);
    310 
    311   CloseFile(fd);
    312   UnmapOrDie(p, page_size);
    313   internal_unlink(tmpfile);
    314 }
    315 #endif
    316