• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 using 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 
39 static const unsigned I = sizeof(int);
40 static const unsigned L = sizeof(long);
41 static const unsigned LL = sizeof(long long);
42 static const unsigned S = sizeof(short);
43 static const unsigned C = sizeof(char);
44 static const unsigned LC = sizeof(wchar_t);
45 static const unsigned D = sizeof(double);
46 static const unsigned LD = sizeof(long double);
47 static const unsigned F = sizeof(float);
48 static const unsigned P = sizeof(char *);
49 
verifyFormatResults(const char * format,unsigned n,const std::vector<unsigned> & computed_sizes,va_list expected_sizes)50 static 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 
63 static const char test_buf[] = "Test string.";
64 static const size_t test_buf_size = sizeof(test_buf);
65 
66 static const unsigned SCANF_ARGS_MAX = 16;
67 
testScanf3(void * ctx,int result,bool allowGnuMalloc,const char * format,...)68 static 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 
testScanf2(const char * format,int scanf_result,bool allowGnuMalloc,unsigned n,va_list expected_sizes)76 static 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 
testScanf(const char * format,unsigned n,...)88 static 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 
testScanfPartial(const char * format,int scanf_result,unsigned n,...)95 static 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 
testScanfNoGnuMalloc(const char * format,unsigned n,...)103 static 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 
TEST(SanitizerCommonInterceptors,Scanf)110 TEST(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 
testPrintf3(void * ctx,const char * format,...)206 static 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 
testPrintf2(const char * format,unsigned n,va_list expected_sizes)213 static 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 
testPrintf(const char * format,unsigned n,...)224 static 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 
TEST(SanitizerCommonInterceptors,Printf)231 TEST(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