blob: 015e32a09e3733c44cc7578267b84ffa45ad9988 [file] [log] [blame]
Alexander Potapenko341588a2012-10-26 13:24:20 +00001//===-- 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//===----------------------------------------------------------------------===//
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080011#include <algorithm>
Alexander Potapenko341588a2012-10-26 13:24:20 +000012
Alexey Samsonov4c9317a2013-02-04 10:16:50 +000013#include "sanitizer_common/sanitizer_common.h"
Alexander Potapenko341588a2012-10-26 13:24:20 +000014#include "sanitizer_common/sanitizer_libc.h"
Sergey Matveeva615b262013-05-14 13:19:33 +000015#include "sanitizer_common/sanitizer_platform.h"
Alexander Potapenko341588a2012-10-26 13:24:20 +000016#include "gtest/gtest.h"
17
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080018#if SANITIZER_WINDOWS
19#define NOMINMAX
20#include <windows.h>
21#undef NOMINMAX
22#endif
23#if SANITIZER_POSIX
Alexey Samsonov4c9317a2013-02-04 10:16:50 +000024# include <sys/stat.h>
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070025# include "sanitizer_common/sanitizer_posix.h"
Alexey Samsonov4c9317a2013-02-04 10:16:50 +000026#endif
27
Alexander Potapenko341588a2012-10-26 13:24:20 +000028// A regression test for internal_memmove() implementation.
29TEST(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}
Kostya Serebryanyeb280932012-12-28 15:24:16 +000036
37TEST(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}
Alexey Samsonov4c9317a2013-02-04 10:16:50 +000056
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +000057struct stat_and_more {
58 struct stat st;
59 unsigned char z;
60};
61
Stephen Hines86277eb2015-03-23 12:06:32 -070062static void temp_file_name(char *buf, size_t bufsize, const char *prefix) {
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080063#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
Stephen Hines86277eb2015-03-23 12:06:32 -070074 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);
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080084#endif
Stephen Hines86277eb2015-03-23 12:06:32 -070085}
86
Alexey Samsonov4c9317a2013-02-04 10:16:50 +000087TEST(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
Stephen Hines86277eb2015-03-23 12:06:32 -070093 char tmpfile[128];
94 temp_file_name(tmpfile, sizeof(tmpfile), "sanitizer_common.fileops.tmp.");
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -070095 fd_t fd = OpenFile(tmpfile, WrOnly);
96 ASSERT_NE(fd, kInvalidFd);
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080097 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);
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700102 CloseFile(fd);
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000103
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800104 EXPECT_TRUE(FileExists(tmpfile));
105
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700106 fd = OpenFile(tmpfile, RdOnly);
107 ASSERT_NE(fd, kInvalidFd);
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800108
109#if SANITIZER_POSIX
110 // The stat wrappers are posix-only.
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000111 uptr fsize = internal_filesize(fd);
112 EXPECT_EQ(len1 + len2, fsize);
113
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000114 struct stat st1, st2, st3;
Stephen Hines86277eb2015-03-23 12:06:32 -0700115 EXPECT_EQ(0u, internal_stat(tmpfile, &st1));
116 EXPECT_EQ(0u, internal_lstat(tmpfile, &st2));
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000117 EXPECT_EQ(0u, internal_fstat(fd, &st3));
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000118 EXPECT_EQ(fsize, (uptr)st3.st_size);
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000119
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));
Peter Collingbourne9578a3e2013-05-08 14:43:49 +0000124 EXPECT_EQ(0u, internal_fstat(fd, &sam.st));
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000125 EXPECT_EQ(0xAB, sam.z);
126 EXPECT_NE(0xAB, sam.st.st_size);
127 EXPECT_NE(0, sam.st.st_size);
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000128#endif
129
130 char buf[64] = {};
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800131 uptr bytes_read = 0;
132 EXPECT_TRUE(ReadFromFile(fd, buf, len1, &bytes_read));
133 EXPECT_EQ(len1, bytes_read);
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000134 EXPECT_EQ(0, internal_memcmp(buf, str1, len1));
135 EXPECT_EQ((char)0, buf[len1 + 1]);
136 internal_memset(buf, 0, len1);
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800137 EXPECT_TRUE(ReadFromFile(fd, buf, len2, &bytes_read));
138 EXPECT_EQ(len2, bytes_read);
Alexey Samsonov4c9317a2013-02-04 10:16:50 +0000139 EXPECT_EQ(0, internal_memcmp(buf, str2, len2));
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700140 CloseFile(fd);
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800141
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
Stephen Hines86277eb2015-03-23 12:06:32 -0700147 internal_unlink(tmpfile);
Stephen Hines2d1fdb22014-05-28 23:58:16 -0700148#endif
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800149}
150
151static const size_t kStrlcpyBufSize = 8;
152void 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}
Evgeniy Stepanov2be3a282013-05-07 12:47:04 +0000168
Alexey Samsonov72870db2013-09-03 13:09:28 +0000169TEST(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'));
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800175
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);
Alexey Samsonov72870db2013-09-03 13:09:28 +0000210}
Stephen Hines86277eb2015-03-23 12:06:32 -0700211
212// FIXME: File manipulations are not yet supported on Windows
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800213#if SANITIZER_POSIX && !SANITIZER_MAC
Stephen Hines86277eb2015-03-23 12:06:32 -0700214TEST(SanitizerCommon, InternalMmapWithOffset) {
215 char tmpfile[128];
216 temp_file_name(tmpfile, sizeof(tmpfile),
217 "sanitizer_common.internalmmapwithoffset.tmp.");
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700218 fd_t fd = OpenFile(tmpfile, RdWr);
219 ASSERT_NE(fd, kInvalidFd);
Stephen Hines86277eb2015-03-23 12:06:32 -0700220
221 uptr page_size = GetPageSizeCached();
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700222 uptr res = internal_ftruncate(fd, page_size * 2);
Stephen Hines86277eb2015-03-23 12:06:32 -0700223 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
Pirama Arumuga Nainar259f7062015-05-06 11:49:53 -0700237 CloseFile(fd);
238 UnmapOrDie(p, page_size);
Stephen Hines86277eb2015-03-23 12:06:32 -0700239 internal_unlink(tmpfile);
240}
241#endif