[mlir] Update Ch-2.md (#121379)
[llvm-project.git] / compiler-rt / lib / sanitizer_common / tests / sanitizer_format_interceptor_test.cpp
blobde96e573ab844cb5042534d524cc6369ae73e39a
1 //===-- sanitizer_format_interceptor_test.cpp -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Tests for *scanf interceptors implementation in sanitizer_common.
11 //===----------------------------------------------------------------------===//
12 #include <wchar.h>
14 #include <algorithm>
15 #include <vector>
17 #include "gtest/gtest.h"
18 #include "interception/interception.h"
19 #include "sanitizer_common/sanitizer_common.h"
20 #include "sanitizer_common/sanitizer_libc.h"
21 #include "sanitizer_test_utils.h"
23 using namespace __sanitizer;
25 #define COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size) \
26 do { \
27 ((std::vector<unsigned> *)ctx)->push_back(size); \
28 ptr = ptr; \
29 } while (0)
31 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
32 COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
34 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
35 COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
37 #define SANITIZER_INTERCEPT_PRINTF 1
38 #include "sanitizer_common/sanitizer_common_interceptors_format.inc"
40 static const unsigned I = sizeof(int);
41 static const unsigned L = sizeof(long);
42 static const unsigned LL = sizeof(long long);
43 static const unsigned S = sizeof(short);
44 static const unsigned C = sizeof(char);
45 static const unsigned LC = sizeof(wchar_t);
46 static const unsigned D = sizeof(double);
47 static const unsigned LD = sizeof(long double);
48 static const unsigned F = sizeof(float);
49 static const unsigned P = sizeof(char *);
51 static void verifyFormatResults(const char *format, unsigned n,
52 const std::vector<unsigned> &computed_sizes,
53 const std::vector<unsigned> &expected_sizes) {
54 // "+ 1" because of the format string
55 ASSERT_EQ(n + 1,
56 computed_sizes.size()) << "Unexpected number of format arguments: '"
57 << format << "'";
58 for (unsigned i = 0; i < n; ++i)
59 EXPECT_EQ(expected_sizes[i], computed_sizes[i + 1])
60 << "Unexpect write size for argument " << i << ", format string '"
61 << format << "'";
64 static const char test_buf[] = "Test string.";
65 static const size_t test_buf_size = sizeof(test_buf);
67 static const unsigned SCANF_ARGS_MAX = 16;
69 static void testScanf3(void *ctx, int result, bool allowGnuMalloc,
70 const char *format, ...) {
71 va_list ap;
72 va_start(ap, format);
73 scanf_common(ctx, result, allowGnuMalloc, format, ap);
74 va_end(ap);
77 static void testScanf2(const char *format, int scanf_result,
78 bool allowGnuMalloc, unsigned n,
79 va_list expected_sizes_va) {
80 std::vector<unsigned> scanf_sizes, expected_sizes;
81 for (unsigned i = 0; i < n; ++i)
82 expected_sizes.push_back(va_arg(expected_sizes_va, unsigned));
84 // 16 args should be enough.
85 testScanf3((void *)&scanf_sizes, scanf_result, allowGnuMalloc, format,
86 test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
87 test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
88 test_buf, test_buf, test_buf, test_buf);
89 verifyFormatResults(format, n, scanf_sizes, expected_sizes);
92 static void testScanf(const char *format, unsigned n, ...) {
93 va_list ap;
94 va_start(ap, n);
95 testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ true, n, ap);
96 va_end(ap);
99 static void testScanfPartial(const char *format, int scanf_result, unsigned n,
100 ...) {
101 va_list ap;
102 va_start(ap, n);
103 testScanf2(format, scanf_result, /* allowGnuMalloc */ true, n, ap);
104 va_end(ap);
107 static void testScanfNoGnuMalloc(const char *format, unsigned n, ...) {
108 va_list ap;
109 va_start(ap, n);
110 testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ false, n, ap);
111 va_end(ap);
114 TEST(SanitizerCommonInterceptors, Scanf) {
115 testScanf("%d", 1, I);
116 testScanf("%d%d%d", 3, I, I, I);
117 testScanf("ab%u%dc", 2, I, I);
118 testScanf("%ld", 1, L);
119 testScanf("%llu", 1, LL);
120 testScanf("%qd", 1, LL);
121 testScanf("a %hd%hhx", 2, S, C);
122 testScanf("%c", 1, C);
123 testScanf("%lc", 1, LC);
125 testScanf("%%", 0);
126 testScanf("a%%", 0);
127 testScanf("a%%b", 0);
128 testScanf("a%%%%b", 0);
129 testScanf("a%%b%%", 0);
130 testScanf("a%%%%%%b", 0);
131 testScanf("a%%%%%b", 0);
132 testScanf("a%%%%%f", 1, F);
133 testScanf("a%%%lxb", 1, L);
134 testScanf("a%lf%%%lxb", 2, D, L);
135 testScanf("%nf", 1, I);
137 testScanf("%10s", 1, 11);
138 testScanf("%10c", 1, 10);
139 testScanf("%10ls", 1, 11 * LC);
140 testScanf("%10lc", 1, 10 * LC);
141 testScanf("%%10s", 0);
142 testScanf("%*10s", 0);
143 testScanf("%*d", 0);
145 testScanf("%4d%8f%c", 3, I, F, C);
146 testScanf("%s%d", 2, test_buf_size, I);
147 testScanf("%[abc]", 1, test_buf_size);
148 testScanf("%4[bcdef]", 1, 5);
149 testScanf("%[]]", 1, test_buf_size);
150 testScanf("%8[^]%d0-9-]%c", 2, 9, C);
152 testScanf("%*[^:]%n:%d:%1[ ]%n", 4, I, I, 2, I);
154 testScanf("%*d%u", 1, I);
156 testScanf("%c%d", 2, C, I);
157 testScanf("%A%lf", 2, F, D);
159 testScanf("s%Las", 1, LD);
160 testScanf("%ar", 1, F);
162 // In the cases with std::min below the format spec can be interpreted as
163 // either floating-something, or (GNU extension) callee-allocated string.
164 // Our conservative implementation reports one of the two possibilities with
165 // the least store range.
166 testScanf("%a[", 0);
167 testScanf("%a[]", 0);
168 testScanf("%a[]]", 1, std::min(F, P));
169 testScanf("%a[abc]", 1, std::min(F, P));
170 testScanf("%a[^abc]", 1, std::min(F, P));
171 testScanf("%a[ab%c] %d", 0);
172 testScanf("%a[^ab%c] %d", 0);
173 testScanf("%as", 1, std::min(F, P));
174 testScanf("%aS", 1, std::min(F, P));
175 testScanf("%a13S", 1, std::min(F, P));
176 testScanf("%alS", 1, std::min(F, P));
178 testScanfNoGnuMalloc("s%Las", 1, LD);
179 testScanfNoGnuMalloc("%ar", 1, F);
180 testScanfNoGnuMalloc("%a[", 1, F);
181 testScanfNoGnuMalloc("%a[]", 1, F);
182 testScanfNoGnuMalloc("%a[]]", 1, F);
183 testScanfNoGnuMalloc("%a[abc]", 1, F);
184 testScanfNoGnuMalloc("%a[^abc]", 1, F);
185 testScanfNoGnuMalloc("%a[ab%c] %d", 3, F, C, I);
186 testScanfNoGnuMalloc("%a[^ab%c] %d", 3, F, C, I);
187 testScanfNoGnuMalloc("%as", 1, F);
188 testScanfNoGnuMalloc("%aS", 1, F);
189 testScanfNoGnuMalloc("%a13S", 1, F);
190 testScanfNoGnuMalloc("%alS", 1, F);
192 testScanf("%5$d", 0);
193 testScanf("%md", 0);
194 testScanf("%m10s", 0);
196 testScanfPartial("%d%d%d%d //1\n", 1, 1, I);
197 testScanfPartial("%d%d%d%d //2\n", 2, 2, I, I);
198 testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I);
199 testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I);
201 testScanfPartial("%d%n%n%d //1\n", 1, 3, I, I, I);
202 testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I);
204 testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, test_buf_size);
205 testScanfPartial("%d%n%n%d %s %s", 4, 6, I, I, I, I, test_buf_size,
206 test_buf_size);
209 TEST(SanitizerCommonInterceptors, ScanfAllocate) {
210 const char *buf = "123456";
211 const wchar_t *wbuf = L"123";
213 // Can not use testScanf() because this case needs a valid pointer to a string
214 // in the scanf argument.
216 std::vector<unsigned> scanf_sizes;
217 testScanf3((void *)&scanf_sizes, 2, /*allowGnuMalloc=*/false, "%mc", &buf);
218 verifyFormatResults("%mc", 2, scanf_sizes, {P, 1u});
221 std::vector<unsigned> scanf_sizes;
222 testScanf3((void *)&scanf_sizes, 2, /*allowGnuMalloc=*/false, "%mC", &wbuf);
223 verifyFormatResults("%mC", 2, scanf_sizes, {P, (unsigned)sizeof(wchar_t)});
226 std::vector<unsigned> scanf_sizes;
227 testScanf3((void *)&scanf_sizes, 2, /*allowGnuMalloc=*/false, "%ms", &buf);
228 verifyFormatResults("%ms", 2, scanf_sizes, {P, unsigned(strlen(buf) + 1)});
229 scanf_sizes.clear();
230 testScanf3((void *)&scanf_sizes, 2, /*allowGnuMalloc=*/false, "%m[0-9]",
231 &buf);
232 verifyFormatResults("%m[0-9]", 2, scanf_sizes,
233 {P, unsigned(strlen(buf) + 1)});
236 std::vector<unsigned> scanf_sizes;
237 testScanf3((void *)&scanf_sizes, 2, /*allowGnuMalloc=*/false, "%mS", &wbuf);
238 verifyFormatResults("%mS", 2, scanf_sizes,
239 {P, unsigned((wcslen(wbuf) + 1) * sizeof(wchar_t))});
243 static void testPrintf3(void *ctx, const char *format, ...) {
244 va_list ap;
245 va_start(ap, format);
246 printf_common(ctx, format, ap);
247 va_end(ap);
250 static void testPrintf2(const char *format, unsigned n,
251 va_list expected_sizes_va) {
252 std::vector<unsigned> printf_sizes, expected_sizes;
253 for (unsigned i = 0; i < n; ++i)
254 expected_sizes.push_back(va_arg(expected_sizes_va, unsigned));
256 // 16 args should be enough.
257 testPrintf3((void *)&printf_sizes, format,
258 test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
259 test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
260 test_buf, test_buf, test_buf, test_buf);
261 verifyFormatResults(format, n, printf_sizes, expected_sizes);
264 static void testPrintf(const char *format, unsigned n, ...) {
265 va_list ap;
266 va_start(ap, n);
267 testPrintf2(format, n, ap);
268 va_end(ap);
271 TEST(SanitizerCommonInterceptors, Printf) {
272 // Only test functionality which differs from scanf
274 // Indexed arguments
275 testPrintf("%5$d", 0);
276 testPrintf("%.*5$d", 0);
278 // errno
279 testPrintf("%0-m", 0);
281 // Dynamic width
282 testPrintf("%*n", 1, I);
283 testPrintf("%*.10n", 1, I);
285 // Precision
286 testPrintf("%10.10n", 1, I);
287 testPrintf("%.3s", 1, 3);
288 testPrintf("%.20s", 1, test_buf_size);
290 // Dynamic precision
291 testPrintf("%.*n", 1, I);
292 testPrintf("%10.*n", 1, I);
294 // Dynamic precision for strings is not implemented yet.
295 testPrintf("%.*s", 1, 0);
297 // Checks for wide-character strings are not implemented yet.
298 testPrintf("%ls", 1, 0);
300 testPrintf("%m", 0);
301 testPrintf("%m%s", 1, test_buf_size);
302 testPrintf("%s%m%s", 2, test_buf_size, test_buf_size);