Home | History | Annotate | 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 
     13 #include "sanitizer_common/sanitizer_common.h"
     14 #include "sanitizer_common/sanitizer_libc.h"
     15 #include "sanitizer_common/sanitizer_platform.h"
     16 #include "gtest/gtest.h"
     17 
     18 #if SANITIZER_WINDOWS
     19 #define NOMINMAX
     20 #include <windows.h>
     21 #undef NOMINMAX
     22 #endif
     23 #if SANITIZER_POSIX
     24 # include <sys/stat.h>
     25 # include "sanitizer_common/sanitizer_posix.h"
     26 #endif
     27 
     28 // A regression test for internal_memmove() implementation.
     29 TEST(SanitizerCommon, InternalMemmoveRegression) {
     30   char src[] = "Hello World";
     31   char *dest = src + 6;
     32   __sanitizer::internal_memmove(dest, src, 5);
     33   EXPECT_EQ(dest[0], src[0]);
     34   EXPECT_EQ(dest[4], src[4]);
     35 }
     36 
     37 TEST(SanitizerCommon, mem_is_zero) {
     38   size_t size = 128;
     39   char *x = new char[size];
     40   memset(x, 0, size);
     41   for (size_t pos = 0; pos < size; pos++) {
     42     x[pos] = 1;
     43     for (size_t beg = 0; beg < size; beg++) {
     44       for (size_t end = beg; end < size; end++) {
     45         // fprintf(stderr, "pos %zd beg %zd end %zd \n", pos, beg, end);
     46         if (beg <= pos && pos < end)
     47           EXPECT_FALSE(__sanitizer::mem_is_zero(x + beg, end - beg));
     48         else
     49           EXPECT_TRUE(__sanitizer::mem_is_zero(x + beg, end - beg));
     50       }
     51     }
     52     x[pos] = 0;
     53   }
     54   delete [] x;
     55 }
     56 
     57 struct stat_and_more {
     58   struct stat st;
     59   unsigned char z;
     60 };
     61 
     62 static void temp_file_name(char *buf, size_t bufsize, const char *prefix) {
     63 #if SANITIZER_WINDOWS
     64   buf[0] = '\0';
     65   char tmp_dir[MAX_PATH];
     66   if (!::GetTempPathA(MAX_PATH, tmp_dir))
     67     return;
     68   // GetTempFileNameA needs a MAX_PATH buffer.
     69   char tmp_path[MAX_PATH];
     70   if (!::GetTempFileNameA(tmp_dir, prefix, 0, tmp_path))
     71     return;
     72   internal_strncpy(buf, tmp_path, bufsize);
     73 #else
     74   const char *tmpdir = "/tmp";
     75 #if SANITIZER_ANDROID
     76   // I don't know a way to query temp directory location on Android without
     77   // going through Java interfaces. The code below is not ideal, but should
     78   // work. May require "adb root", but it is needed for almost any use of ASan
     79   // on Android already.
     80   tmpdir = GetEnv("EXTERNAL_STORAGE");
     81 #endif
     82   u32 uid = GetUid();
     83   internal_snprintf(buf, bufsize, "%s/%s%d", tmpdir, prefix, uid);
     84 #endif
     85 }
     86 
     87 TEST(SanitizerCommon, FileOps) {
     88   const char *str1 = "qwerty";
     89   uptr len1 = internal_strlen(str1);
     90   const char *str2 = "zxcv";
     91   uptr len2 = internal_strlen(str2);
     92 
     93   char tmpfile[128];
     94   temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp.");
     95   fd_t fd = OpenFile(tmpfile, WrOnly);
     96   ASSERT_NE(fd, kInvalidFd);
     97   uptr bytes_written = 0;
     98   EXPECT_TRUE(WriteToFile(fd, str1, len1, &bytes_written));
     99   EXPECT_EQ(len1, bytes_written);
    100   EXPECT_TRUE(WriteToFile(fd, str2, len2, &bytes_written));
    101   EXPECT_EQ(len2, bytes_written);
    102   CloseFile(fd);
    103 
    104   EXPECT_TRUE(FileExists(tmpfile));
    105 
    106   fd = OpenFile(tmpfile, RdOnly);
    107   ASSERT_NE(fd, kInvalidFd);
    108 
    109 #if SANITIZER_POSIX
    110   // The stat wrappers are posix-only.
    111   uptr fsize = internal_filesize(fd);
    112   EXPECT_EQ(len1 + len2, fsize);
    113 
    114   struct stat st1, st2, st3;
    115   EXPECT_EQ(0u, internal_stat(tmpfile, &st1));
    116   EXPECT_EQ(0u, internal_lstat(tmpfile, &st2));
    117   EXPECT_EQ(0u, internal_fstat(fd, &st3));
    118   EXPECT_EQ(fsize, (uptr)st3.st_size);
    119 
    120   // Verify that internal_fstat does not write beyond the end of the supplied
    121   // buffer.
    122   struct stat_and_more sam;
    123   memset(&sam, 0xAB, sizeof(sam));
    124   EXPECT_EQ(0u, internal_fstat(fd, &sam.st));
    125   EXPECT_EQ(0xAB, sam.z);
    126   EXPECT_NE(0xAB, sam.st.st_size);
    127   EXPECT_NE(0, sam.st.st_size);
    128 #endif
    129 
    130   char buf[64] = {};
    131   uptr bytes_read = 0;
    132   EXPECT_TRUE(ReadFromFile(fd, buf, len1, &bytes_read));
    133   EXPECT_EQ(len1, bytes_read);
    134   EXPECT_EQ(0, internal_memcmp(buf, str1, len1));
    135   EXPECT_EQ((char)0, buf[len1 + 1]);
    136   internal_memset(buf, 0, len1);
    137   EXPECT_TRUE(ReadFromFile(fd, buf, len2, &bytes_read));
    138   EXPECT_EQ(len2, bytes_read);
    139   EXPECT_EQ(0, internal_memcmp(buf, str2, len2));
    140   CloseFile(fd);
    141 
    142 #if SANITIZER_WINDOWS
    143   // No sanitizer needs to delete a file on Windows yet. If we ever do, we can
    144   // add a portable wrapper and test it from here.
    145   ::DeleteFileA(&tmpfile[0]);
    146 #else
    147   internal_unlink(tmpfile);
    148 #endif
    149 }
    150 
    151 static const size_t kStrlcpyBufSize = 8;
    152 void test_internal_strlcpy(char *dbuf, const char *sbuf) {
    153   uptr retval = 0;
    154   retval = internal_strlcpy(dbuf, sbuf, kStrlcpyBufSize);
    155   EXPECT_EQ(internal_strncmp(dbuf, sbuf, kStrlcpyBufSize - 1), 0);
    156   EXPECT_EQ(internal_strlen(dbuf),
    157             std::min(internal_strlen(sbuf), (uptr)(kStrlcpyBufSize - 1)));
    158   EXPECT_EQ(retval, internal_strlen(sbuf));
    159 
    160   // Test with shorter maxlen.
    161   uptr maxlen = 2;
    162   if (internal_strlen(sbuf) > maxlen) {
    163     retval = internal_strlcpy(dbuf, sbuf, maxlen);
    164     EXPECT_EQ(internal_strncmp(dbuf, sbuf, maxlen - 1), 0);
    165     EXPECT_EQ(internal_strlen(dbuf), maxlen - 1);
    166   }
    167 }
    168 
    169 TEST(SanitizerCommon, InternalStrFunctions) {
    170   const char *haystack = "haystack";
    171   EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y'));
    172   EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y'));
    173   EXPECT_EQ(0, internal_strchr(haystack, 'z'));
    174   EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z'));
    175 
    176   char dbuf[kStrlcpyBufSize] = {};
    177   const char *samesizestr = "1234567";
    178   const char *shortstr = "123";
    179   const char *longerstr = "123456789";
    180 
    181   // Test internal_strlcpy.
    182   internal_strlcpy(dbuf, shortstr, 0);
    183   EXPECT_EQ(dbuf[0], 0);
    184   EXPECT_EQ(dbuf[0], 0);
    185   test_internal_strlcpy(dbuf, samesizestr);
    186   test_internal_strlcpy(dbuf, shortstr);
    187   test_internal_strlcpy(dbuf, longerstr);
    188 
    189   // Test internal_strlcat.
    190   char dcatbuf[kStrlcpyBufSize] = {};
    191   uptr retval = 0;
    192   retval = internal_strlcat(dcatbuf, "aaa", 0);
    193   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)0);
    194   EXPECT_EQ(retval, (uptr)3);
    195 
    196   retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
    197   EXPECT_EQ(internal_strcmp(dcatbuf, "123"), 0);
    198   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)3);
    199   EXPECT_EQ(retval, (uptr)3);
    200 
    201   retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
    202   EXPECT_EQ(internal_strcmp(dcatbuf, "123123"), 0);
    203   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)6);
    204   EXPECT_EQ(retval, (uptr)6);
    205 
    206   retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
    207   EXPECT_EQ(internal_strcmp(dcatbuf, "1231231"), 0);
    208   EXPECT_EQ(internal_strlen(dcatbuf), (uptr)7);
    209   EXPECT_EQ(retval, (uptr)9);
    210 }
    211 
    212 // FIXME: File manipulations are not yet supported on Windows
    213 #if SANITIZER_POSIX && !SANITIZER_MAC
    214 TEST(SanitizerCommon, InternalMmapWithOffset) {
    215   char tmpfile[128];
    216   temp_file_name(tmpfile, sizeof(tmpfile),
    217                  "sanitizer_common.internalmmapwithoffset.tmp.");
    218   fd_t fd = OpenFile(tmpfile, RdWr);
    219   ASSERT_NE(fd, kInvalidFd);
    220 
    221   uptr page_size = GetPageSizeCached();
    222   uptr res = internal_ftruncate(fd, page_size * 2);
    223   ASSERT_FALSE(internal_iserror(res));
    224 
    225   res = internal_lseek(fd, page_size, SEEK_SET);
    226   ASSERT_FALSE(internal_iserror(res));
    227 
    228   res = internal_write(fd, "AB", 2);
    229   ASSERT_FALSE(internal_iserror(res));
    230 
    231   char *p = (char *)MapWritableFileToMemory(nullptr, page_size, fd, page_size);
    232   ASSERT_NE(nullptr, p);
    233 
    234   ASSERT_EQ('A', p[0]);
    235   ASSERT_EQ('B', p[1]);
    236 
    237   CloseFile(fd);
    238   UnmapOrDie(p, page_size);
    239   internal_unlink(tmpfile);
    240 }
    241 #endif
    242