From: Evgeniy Stepanov Date: Mon, 11 Feb 2013 15:16:48 +0000 (+0000) Subject: [sanitizer] scanf: don't report stores that did not happen. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=455c72d25eaa886b60df9a1fddb8951f1d6d950c;p=platform%2Fupstream%2Fllvm.git [sanitizer] scanf: don't report stores that did not happen. Respect REAL(scanf) return value and don't report memory stores that could potentially happen, but did not. llvm-svn: 174887 --- diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 918c16f..ba923e7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -157,7 +157,8 @@ INTERCEPTOR(int, vscanf, const char *format, va_list ap) { // NOLINT va_list aq; va_copy(aq, ap); int res = REAL(vscanf)(format, ap); // NOLINT - scanf_common(ctx, format, aq); + if (res > 0) + scanf_common(ctx, res, format, aq); va_end(aq); return res; } @@ -169,7 +170,8 @@ INTERCEPTOR(int, vsscanf, const char *str, const char *format, // NOLINT va_list aq; va_copy(aq, ap); int res = REAL(vsscanf)(str, format, ap); // NOLINT - scanf_common(ctx, format, aq); + if (res > 0) + scanf_common(ctx, res, format, aq); va_end(aq); // FIXME: read of str return res; @@ -182,7 +184,8 @@ INTERCEPTOR(int, vfscanf, void *stream, const char *format, // NOLINT va_list aq; va_copy(aq, ap); int res = REAL(vfscanf)(stream, format, ap); // NOLINT - scanf_common(ctx, format, aq); + if (res > 0) + scanf_common(ctx, res, format, aq); va_end(aq); return res; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc index 50ce70f..9ab5ae2 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc @@ -15,10 +15,10 @@ #include struct ScanfDirective { - int argIdx; // argument index, or -1 of not specified ("%n$") + int argIdx; // argument index, or -1 of not specified ("%n$") int fieldWidth; bool suppressed; // suppress assignment ("*") - bool allocate; // allocate space ("m") + bool allocate; // allocate space ("m") char lengthModifier[2]; char convSpecifier; bool maybeGnuMalloc; @@ -270,10 +270,13 @@ static int scanf_get_store_size(ScanfDirective *dir) { // Common part of *scanf interceptors. // Process format string and va_list, and report all store ranges. -static void scanf_common(void *ctx, const char *format, va_list aq) { +// Stops when "consuming" n_inputs input items. +static void scanf_common(void *ctx, int n_inputs, const char *format, + va_list aq) { + CHECK_GT(n_inputs, 0); const char *p = format; - while (p) { + while (*p && n_inputs) { ScanfDirective dir; p = scanf_parse_next(p, &dir); if (!p) @@ -293,10 +296,12 @@ static void scanf_common(void *ctx, const char *format, va_list aq) { int size = scanf_get_store_size(&dir); if (size == SSS_INVALID) break; - void *p = va_arg(aq, void *); + void *argp = va_arg(aq, void *); + if (dir.convSpecifier != 'n') + --n_inputs; if (size == SSS_STRLEN) { - size = internal_strlen((const char *)p) + 1; + size = internal_strlen((const char *)argp) + 1; } - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, size); + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, argp, size); } } diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc index 1caf21d..91a6594 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc @@ -24,32 +24,44 @@ using namespace __sanitizer; #include "sanitizer_common/sanitizer_common_interceptors_scanf.inc" -static void testScanf2(void *ctx, const char *format, ...) { +static const char scanf_buf[] = "Test string."; +static size_t scanf_buf_size = sizeof(scanf_buf); +static const unsigned SCANF_ARGS_MAX = 16; + +static void testScanf3(void *ctx, int result, const char *format, ...) { va_list ap; va_start(ap, format); - scanf_common(ctx, format, ap); + scanf_common(ctx, result, format, ap); va_end(ap); } -static const char scanf_buf[] = "Test string."; -static size_t scanf_buf_size = sizeof(scanf_buf); - -static void testScanf(const char *format, unsigned n, ...) { +static void testScanf2(const char *format, int scanf_result, unsigned n, va_list expected_sizes) { std::vector scanf_sizes; // 16 args should be enough. - testScanf2((void *)&scanf_sizes, format, + testScanf3((void *)&scanf_sizes, scanf_result, format, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf, scanf_buf); ASSERT_EQ(n, scanf_sizes.size()) << "Unexpected number of format arguments: '" << format << "'"; - va_list ap; - va_start(ap, n); for (unsigned i = 0; i < n; ++i) - EXPECT_EQ(va_arg(ap, unsigned), scanf_sizes[i]) << + EXPECT_EQ(va_arg(expected_sizes, unsigned), scanf_sizes[i]) << "Unexpect write size for argument " << i << ", format string '" << format << "'"; +} + +static void testScanf(const char *format, unsigned n, ...) { + va_list ap; + va_start(ap, n); + testScanf2(format, SCANF_ARGS_MAX, n, ap); + va_end(ap); +} + +static void testScanfPartial(const char *format, int scanf_result, unsigned n, ...) { + va_list ap; + va_start(ap, n); + testScanf2(format, scanf_result, n, ap); va_end(ap); } @@ -127,4 +139,15 @@ TEST(SanitizerCommonInterceptors, Scanf) { testScanf("%5$d", 0); testScanf("%md", 0); testScanf("%m10s", 0); + + testScanfPartial("%d%d%d%d //1\n", 1, 1, I); + testScanfPartial("%d%d%d%d //2\n", 2, 2, I, I); + testScanfPartial("%d%d%d%d //3\n", 3, 3, I, I, I); + testScanfPartial("%d%d%d%d //4\n", 4, 4, I, I, I, I); + + testScanfPartial("%d%n%n%d //1\n", 1, 1, I); + testScanfPartial("%d%n%n%d //2\n", 2, 4, I, I, I, I); + + testScanfPartial("%d%n%n%d %s %s", 3, 5, I, I, I, I, scanf_buf_size); + testScanfPartial("%d%n%n%d %s %s", 4, 6, I, I, I, I, scanf_buf_size, scanf_buf_size); }