1 //===-- sanitizer_format_interceptor_test.cpp -----------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Tests for *scanf interceptors implementation in sanitizer_common.
11 //===----------------------------------------------------------------------===//
15 #include "interception/interception.h"
16 #include "sanitizer_test_utils.h"
17 #include "sanitizer_common/sanitizer_libc.h"
18 #include "sanitizer_common/sanitizer_common.h"
19 #include "gtest/gtest.h"
21 using namespace __sanitizer
;
23 #define COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size) \
25 ((std::vector<unsigned> *)ctx)->push_back(size); \
29 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
30 COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
32 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
33 COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
35 #define SANITIZER_INTERCEPT_PRINTF 1
36 #include "sanitizer_common/sanitizer_common_interceptors_format.inc"
38 static const unsigned I
= sizeof(int);
39 static const unsigned L
= sizeof(long);
40 static const unsigned LL
= sizeof(long long);
41 static const unsigned S
= sizeof(short);
42 static const unsigned C
= sizeof(char);
43 static const unsigned LC
= sizeof(wchar_t);
44 static const unsigned D
= sizeof(double);
45 static const unsigned LD
= sizeof(long double);
46 static const unsigned F
= sizeof(float);
47 static const unsigned P
= sizeof(char *);
49 static void verifyFormatResults(const char *format
, unsigned n
,
50 const std::vector
<unsigned> &computed_sizes
,
51 const std::vector
<unsigned> &expected_sizes
) {
52 // "+ 1" because of the format string
54 computed_sizes
.size()) << "Unexpected number of format arguments: '"
56 for (unsigned i
= 0; i
< n
; ++i
)
57 EXPECT_EQ(expected_sizes
[i
], computed_sizes
[i
+ 1])
58 << "Unexpect write size for argument " << i
<< ", format string '"
62 static const char test_buf
[] = "Test string.";
63 static const size_t test_buf_size
= sizeof(test_buf
);
65 static const unsigned SCANF_ARGS_MAX
= 16;
67 static void testScanf3(void *ctx
, int result
, bool allowGnuMalloc
,
68 const char *format
, ...) {
71 scanf_common(ctx
, result
, allowGnuMalloc
, format
, ap
);
75 static void testScanf2(const char *format
, int scanf_result
,
76 bool allowGnuMalloc
, unsigned n
,
77 va_list expected_sizes_va
) {
78 std::vector
<unsigned> scanf_sizes
, expected_sizes
;
79 for (unsigned i
= 0; i
< n
; ++i
)
80 expected_sizes
.push_back(va_arg(expected_sizes_va
, unsigned));
82 // 16 args should be enough.
83 testScanf3((void *)&scanf_sizes
, scanf_result
, allowGnuMalloc
, format
,
84 test_buf
, test_buf
, test_buf
, test_buf
, test_buf
, test_buf
,
85 test_buf
, test_buf
, test_buf
, test_buf
, test_buf
, test_buf
,
86 test_buf
, test_buf
, test_buf
, test_buf
);
87 verifyFormatResults(format
, n
, scanf_sizes
, expected_sizes
);
90 static void testScanf(const char *format
, unsigned n
, ...) {
93 testScanf2(format
, SCANF_ARGS_MAX
, /* allowGnuMalloc */ true, n
, ap
);
97 static void testScanfPartial(const char *format
, int scanf_result
, unsigned n
,
101 testScanf2(format
, scanf_result
, /* allowGnuMalloc */ true, n
, ap
);
105 static void testScanfNoGnuMalloc(const char *format
, unsigned n
, ...) {
108 testScanf2(format
, SCANF_ARGS_MAX
, /* allowGnuMalloc */ false, n
, ap
);
112 TEST(SanitizerCommonInterceptors
, Scanf
) {
113 testScanf("%d", 1, I
);
114 testScanf("%d%d%d", 3, I
, I
, I
);
115 testScanf("ab%u%dc", 2, I
, I
);
116 testScanf("%ld", 1, L
);
117 testScanf("%llu", 1, LL
);
118 testScanf("%qd", 1, LL
);
119 testScanf("a %hd%hhx", 2, S
, C
);
120 testScanf("%c", 1, C
);
121 testScanf("%lc", 1, LC
);
125 testScanf("a%%b", 0);
126 testScanf("a%%%%b", 0);
127 testScanf("a%%b%%", 0);
128 testScanf("a%%%%%%b", 0);
129 testScanf("a%%%%%b", 0);
130 testScanf("a%%%%%f", 1, F
);
131 testScanf("a%%%lxb", 1, L
);
132 testScanf("a%lf%%%lxb", 2, D
, L
);
133 testScanf("%nf", 1, I
);
135 testScanf("%10s", 1, 11);
136 testScanf("%10c", 1, 10);
137 testScanf("%10ls", 1, 11 * LC
);
138 testScanf("%10lc", 1, 10 * LC
);
139 testScanf("%%10s", 0);
140 testScanf("%*10s", 0);
143 testScanf("%4d%8f%c", 3, I
, F
, C
);
144 testScanf("%s%d", 2, test_buf_size
, I
);
145 testScanf("%[abc]", 1, test_buf_size
);
146 testScanf("%4[bcdef]", 1, 5);
147 testScanf("%[]]", 1, test_buf_size
);
148 testScanf("%8[^]%d0-9-]%c", 2, 9, C
);
150 testScanf("%*[^:]%n:%d:%1[ ]%n", 4, I
, I
, 2, I
);
152 testScanf("%*d%u", 1, I
);
154 testScanf("%c%d", 2, C
, I
);
155 testScanf("%A%lf", 2, F
, D
);
157 testScanf("s%Las", 1, LD
);
158 testScanf("%ar", 1, F
);
160 // In the cases with std::min below the format spec can be interpreted as
161 // either floating-something, or (GNU extension) callee-allocated string.
162 // Our conservative implementation reports one of the two possibilities with
163 // the least store range.
165 testScanf("%a[]", 0);
166 testScanf("%a[]]", 1, std::min(F
, P
));
167 testScanf("%a[abc]", 1, std::min(F
, P
));
168 testScanf("%a[^abc]", 1, std::min(F
, P
));
169 testScanf("%a[ab%c] %d", 0);
170 testScanf("%a[^ab%c] %d", 0);
171 testScanf("%as", 1, std::min(F
, P
));
172 testScanf("%aS", 1, std::min(F
, P
));
173 testScanf("%a13S", 1, std::min(F
, P
));
174 testScanf("%alS", 1, std::min(F
, P
));
176 testScanfNoGnuMalloc("s%Las", 1, LD
);
177 testScanfNoGnuMalloc("%ar", 1, F
);
178 testScanfNoGnuMalloc("%a[", 1, F
);
179 testScanfNoGnuMalloc("%a[]", 1, F
);
180 testScanfNoGnuMalloc("%a[]]", 1, F
);
181 testScanfNoGnuMalloc("%a[abc]", 1, F
);
182 testScanfNoGnuMalloc("%a[^abc]", 1, F
);
183 testScanfNoGnuMalloc("%a[ab%c] %d", 3, F
, C
, I
);
184 testScanfNoGnuMalloc("%a[^ab%c] %d", 3, F
, C
, I
);
185 testScanfNoGnuMalloc("%as", 1, F
);
186 testScanfNoGnuMalloc("%aS", 1, F
);
187 testScanfNoGnuMalloc("%a13S", 1, F
);
188 testScanfNoGnuMalloc("%alS", 1, F
);
190 testScanf("%5$d", 0);
192 testScanf("%m10s", 0);
194 testScanfPartial("%d%d%d%d //1\n", 1, 1, I
);
195 testScanfPartial("%d%d%d%d //2\n", 2, 2, I
, I
);
196 testScanfPartial("%d%d%d%d //3\n", 3, 3, I
, I
, I
);
197 testScanfPartial("%d%d%d%d //4\n", 4, 4, I
, I
, I
, I
);
199 testScanfPartial("%d%n%n%d //1\n", 1, 3, I
, I
, I
);
200 testScanfPartial("%d%n%n%d //2\n", 2, 4, I
, I
, I
, I
);
202 testScanfPartial("%d%n%n%d %s %s", 3, 5, I
, I
, I
, I
, test_buf_size
);
203 testScanfPartial("%d%n%n%d %s %s", 4, 6, I
, I
, I
, I
, test_buf_size
,
207 TEST(SanitizerCommonInterceptors
, ScanfAllocate
) {
208 const char *buf
= "123456";
210 // Can not use testScanf() because this case needs a valid pointer to a string
211 // in the scanf argument.
213 std::vector
<unsigned> scanf_sizes
;
214 testScanf3((void *)&scanf_sizes
, 2, /*allowGnuMalloc=*/false, "%ms", &buf
);
215 verifyFormatResults("%ms", 2, scanf_sizes
,
216 {P
, (unsigned)(strlen(buf
) + 1)});
220 std::vector
<unsigned> scanf_sizes
;
221 testScanf3((void *)&scanf_sizes
, 2, /*allowGnuMalloc=*/false, "%mc", &buf
);
222 verifyFormatResults("%mc", 2, scanf_sizes
,
223 {P
, (unsigned)(strlen(buf
) + 1)});
227 static void testPrintf3(void *ctx
, const char *format
, ...) {
229 va_start(ap
, format
);
230 printf_common(ctx
, format
, ap
);
234 static void testPrintf2(const char *format
, unsigned n
,
235 va_list expected_sizes_va
) {
236 std::vector
<unsigned> printf_sizes
, expected_sizes
;
237 for (unsigned i
= 0; i
< n
; ++i
)
238 expected_sizes
.push_back(va_arg(expected_sizes_va
, unsigned));
240 // 16 args should be enough.
241 testPrintf3((void *)&printf_sizes
, format
,
242 test_buf
, test_buf
, test_buf
, test_buf
, test_buf
, test_buf
,
243 test_buf
, test_buf
, test_buf
, test_buf
, test_buf
, test_buf
,
244 test_buf
, test_buf
, test_buf
, test_buf
);
245 verifyFormatResults(format
, n
, printf_sizes
, expected_sizes
);
248 static void testPrintf(const char *format
, unsigned n
, ...) {
251 testPrintf2(format
, n
, ap
);
255 TEST(SanitizerCommonInterceptors
, Printf
) {
256 // Only test functionality which differs from scanf
259 testPrintf("%5$d", 0);
260 testPrintf("%.*5$d", 0);
263 testPrintf("%0-m", 0);
266 testPrintf("%*n", 1, I
);
267 testPrintf("%*.10n", 1, I
);
270 testPrintf("%10.10n", 1, I
);
271 testPrintf("%.3s", 1, 3);
272 testPrintf("%.20s", 1, test_buf_size
);
275 testPrintf("%.*n", 1, I
);
276 testPrintf("%10.*n", 1, I
);
278 // Dynamic precision for strings is not implemented yet.
279 testPrintf("%.*s", 1, 0);
281 // Checks for wide-character strings are not implemented yet.
282 testPrintf("%ls", 1, 0);
285 testPrintf("%m%s", 1, test_buf_size
);
286 testPrintf("%s%m%s", 2, test_buf_size
, test_buf_size
);