1//===-- sanitizer_format_interceptor_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//
10// Tests for *scanf interceptors implementation in sanitizer_common.
11//
12//===----------------------------------------------------------------------===//
13#include <algorithm>
14#include <vector>
15
16#include "interception/interception.h"
17#include "sanitizer_test_utils.h"
18#include "sanitizer_common/sanitizer_libc.h"
19#include "sanitizer_common/sanitizer_common.h"
20#include "gtest/gtest.h"
21
22using namespace __sanitizer;
23
24#define COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)                    \
25  do {                                                                         \
26    ((std::vector<unsigned> *)ctx)->push_back(size);                           \
27    ptr = ptr;                                                                 \
28  } while (0)
29
30#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)                          \
31  COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
32
33#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                         \
34  COMMON_INTERCEPTOR_READ_WRITE_RANGE(ctx, ptr, size)
35
36#define SANITIZER_INTERCEPT_PRINTF 1
37#include "sanitizer_common/sanitizer_common_interceptors_format.inc"
38
39static const unsigned I = sizeof(int);
40static const unsigned L = sizeof(long);
41static const unsigned LL = sizeof(long long);
42static const unsigned S = sizeof(short);
43static const unsigned C = sizeof(char);
44static const unsigned LC = sizeof(wchar_t);
45static const unsigned D = sizeof(double);
46static const unsigned LD = sizeof(long double);
47static const unsigned F = sizeof(float);
48static const unsigned P = sizeof(char *);
49
50static void verifyFormatResults(const char *format, unsigned n,
51                                const std::vector<unsigned> &computed_sizes,
52                                va_list expected_sizes) {
53  // "+ 1" because of format string
54  ASSERT_EQ(n + 1,
55            computed_sizes.size()) << "Unexpected number of format arguments: '"
56                                   << format << "'";
57  for (unsigned i = 0; i < n; ++i)
58    EXPECT_EQ(va_arg(expected_sizes, unsigned), computed_sizes[i + 1])
59        << "Unexpect write size for argument " << i << ", format string '"
60        << format << "'";
61}
62
63static const char test_buf[] = "Test string.";
64static const size_t test_buf_size = sizeof(test_buf);
65
66static const unsigned SCANF_ARGS_MAX = 16;
67
68static void testScanf3(void *ctx, int result, bool allowGnuMalloc,
69                       const char *format, ...) {
70  va_list ap;
71  va_start(ap, format);
72  scanf_common(ctx, result, allowGnuMalloc, format, ap);
73  va_end(ap);
74}
75
76static void testScanf2(const char *format, int scanf_result,
77                       bool allowGnuMalloc, unsigned n,
78                       va_list expected_sizes) {
79  std::vector<unsigned> scanf_sizes;
80  // 16 args should be enough.
81  testScanf3((void *)&scanf_sizes, scanf_result, allowGnuMalloc, format,
82             test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
83             test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
84             test_buf, test_buf, test_buf, test_buf);
85  verifyFormatResults(format, n, scanf_sizes, expected_sizes);
86}
87
88static void testScanf(const char *format, unsigned n, ...) {
89  va_list ap;
90  va_start(ap, n);
91  testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ true, n, ap);
92  va_end(ap);
93}
94
95static void testScanfPartial(const char *format, int scanf_result, unsigned n,
96                             ...) {
97  va_list ap;
98  va_start(ap, n);
99  testScanf2(format, scanf_result, /* allowGnuMalloc */ true,  n, ap);
100  va_end(ap);
101}
102
103static void testScanfNoGnuMalloc(const char *format, unsigned n, ...) {
104  va_list ap;
105  va_start(ap, n);
106  testScanf2(format, SCANF_ARGS_MAX, /* allowGnuMalloc */ false, n, ap);
107  va_end(ap);
108}
109
110TEST(SanitizerCommonInterceptors, Scanf) {
111  testScanf("%d", 1, I);
112  testScanf("%d%d%d", 3, I, I, I);
113  testScanf("ab%u%dc", 2, I, I);
114  testScanf("%ld", 1, L);
115  testScanf("%llu", 1, LL);
116  testScanf("%qd", 1, LL);
117  testScanf("a %hd%hhx", 2, S, C);
118  testScanf("%c", 1, C);
119  testScanf("%lc", 1, LC);
120
121  testScanf("%%", 0);
122  testScanf("a%%", 0);
123  testScanf("a%%b", 0);
124  testScanf("a%%%%b", 0);
125  testScanf("a%%b%%", 0);
126  testScanf("a%%%%%%b", 0);
127  testScanf("a%%%%%b", 0);
128  testScanf("a%%%%%f", 1, F);
129  testScanf("a%%%lxb", 1, L);
130  testScanf("a%lf%%%lxb", 2, D, L);
131  testScanf("%nf", 1, I);
132
133  testScanf("%10s", 1, 11);
134  testScanf("%10c", 1, 10);
135  testScanf("%10ls", 1, 11 * LC);
136  testScanf("%10lc", 1, 10 * LC);
137  testScanf("%%10s", 0);
138  testScanf("%*10s", 0);
139  testScanf("%*d", 0);
140
141  testScanf("%4d%8f%c", 3, I, F, C);
142  testScanf("%s%d", 2, test_buf_size, I);
143  testScanf("%[abc]", 1, test_buf_size);
144  testScanf("%4[bcdef]", 1, 5);
145  testScanf("%[]]", 1, test_buf_size);
146  testScanf("%8[^]%d0-9-]%c", 2, 9, C);
147
148  testScanf("%*[^:]%n:%d:%1[ ]%n", 4, I, I, 2, I);
149
150  testScanf("%*d%u", 1, I);
151
152  testScanf("%c%d", 2, C, I);
153  testScanf("%A%lf", 2, F, D);
154
155  testScanf("%ms %Lf", 2, P, LD);
156  testScanf("s%Las", 1, LD);
157  testScanf("%ar", 1, F);
158
159  // In the cases with std::min below the format spec can be interpreted as
160  // either floating-something, or (GNU extension) callee-allocated string.
161  // Our conservative implementation reports one of the two possibilities with
162  // the least store range.
163  testScanf("%a[", 0);
164  testScanf("%a[]", 0);
165  testScanf("%a[]]", 1, std::min(F, P));
166  testScanf("%a[abc]", 1, std::min(F, P));
167  testScanf("%a[^abc]", 1, std::min(F, P));
168  testScanf("%a[ab%c] %d", 0);
169  testScanf("%a[^ab%c] %d", 0);
170  testScanf("%as", 1, std::min(F, P));
171  testScanf("%aS", 1, std::min(F, P));
172  testScanf("%a13S", 1, std::min(F, P));
173  testScanf("%alS", 1, std::min(F, P));
174
175  testScanfNoGnuMalloc("s%Las", 1, LD);
176  testScanfNoGnuMalloc("%ar", 1, F);
177  testScanfNoGnuMalloc("%a[", 1, F);
178  testScanfNoGnuMalloc("%a[]", 1, F);
179  testScanfNoGnuMalloc("%a[]]", 1, F);
180  testScanfNoGnuMalloc("%a[abc]", 1, F);
181  testScanfNoGnuMalloc("%a[^abc]", 1, F);
182  testScanfNoGnuMalloc("%a[ab%c] %d", 3, F, C, I);
183  testScanfNoGnuMalloc("%a[^ab%c] %d", 3, F, C, I);
184  testScanfNoGnuMalloc("%as", 1, F);
185  testScanfNoGnuMalloc("%aS", 1, F);
186  testScanfNoGnuMalloc("%a13S", 1, F);
187  testScanfNoGnuMalloc("%alS", 1, F);
188
189  testScanf("%5$d", 0);
190  testScanf("%md", 0);
191  testScanf("%m10s", 0);
192
193  testScanfPartial("%d%d%d%d //1\n", 1, 1, I);
194  testScanfPartial("%d%d%d%d //2\n", 2, 2, I, I);
195  testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I);
196  testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I);
197
198  testScanfPartial("%d%n%n%d //1\n", 1, 3, I, I, I);
199  testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I);
200
201  testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, test_buf_size);
202  testScanfPartial("%d%n%n%d %s %s", 4, 6, I, I, I, I, test_buf_size,
203                   test_buf_size);
204}
205
206static void testPrintf3(void *ctx, const char *format, ...) {
207  va_list ap;
208  va_start(ap, format);
209  printf_common(ctx, format, ap);
210  va_end(ap);
211}
212
213static void testPrintf2(const char *format, unsigned n,
214                       va_list expected_sizes) {
215  std::vector<unsigned> printf_sizes;
216  // 16 args should be enough.
217  testPrintf3((void *)&printf_sizes, format,
218             test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
219             test_buf, test_buf, test_buf, test_buf, test_buf, test_buf,
220             test_buf, test_buf, test_buf, test_buf);
221  verifyFormatResults(format, n, printf_sizes, expected_sizes);
222}
223
224static void testPrintf(const char *format, unsigned n, ...) {
225  va_list ap;
226  va_start(ap, n);
227  testPrintf2(format, n, ap);
228  va_end(ap);
229}
230
231TEST(SanitizerCommonInterceptors, Printf) {
232  // Only test functionality which differs from scanf
233
234  // Indexed arguments
235  testPrintf("%5$d", 0);
236  testPrintf("%.*5$d", 0);
237
238  // errno
239  testPrintf("%0-m", 0);
240
241  // Dynamic width
242  testPrintf("%*n", 1, I);
243  testPrintf("%*.10n", 1, I);
244
245  // Precision
246  testPrintf("%10.10n", 1, I);
247  testPrintf("%.3s", 1, 3);
248  testPrintf("%.20s", 1, test_buf_size);
249
250  // Dynamic precision
251  testPrintf("%.*n", 1, I);
252  testPrintf("%10.*n", 1, I);
253
254  // Dynamic precision for strings is not implemented yet.
255  testPrintf("%.*s", 1, 0);
256
257  // Checks for wide-character strings are not implemented yet.
258  testPrintf("%ls", 1, 0);
259}
260