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