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.
TEST(SanitizerCommon,InternalMemmoveRegression)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 
TEST(SanitizerCommon,mem_is_zero)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 
temp_file_name(char * buf,size_t bufsize,const char * prefix)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 
TEST(SanitizerCommon,FileOps)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;
test_internal_strlcpy(char * dbuf,const char * sbuf)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 
TEST(SanitizerCommon,InternalStrFunctions)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
TEST(SanitizerCommon,InternalMmapWithOffset)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