xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/sanitizer_common/tests/sanitizer_libc_test.cc (revision a7c257b03e4462df2b1020128fb82716512d7856)
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.
TEST(SanitizerCommon,InternalMemmoveRegression)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 
TEST(SanitizerCommon,mem_is_zero)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 
temp_file_name(char * buf,size_t bufsize,const char * prefix)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 
Unlink(const char * path)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 
TEST(SanitizerCommon,FileOps)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> {
SetUp()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 
TearDown()182   void TearDown() override { Unlink(file_name_); }
183 
184  protected:
185   char file_name_[256];
186   std::vector<char> data_;
187 };
188 
TEST_P(SanitizerCommonFileTest,ReadFileToBuffer)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 
TEST_P(SanitizerCommonFileTest,ReadFileToBufferHalf)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 
TEST_P(SanitizerCommonFileTest,ReadFileToVector)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 
TEST_P(SanitizerCommonFileTest,ReadFileToVectorHalf)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;
test_internal_strlcpy(char * dbuf,const char * sbuf)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 
TEST(SanitizerCommon,InternalStrFunctions)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
TEST(SanitizerCommon,InternalMmapWithOffset)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