[compiler-rt] r174887 - [sanitizer] scanf: don't report stores that did not happen.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Mon Feb 11 07:16:48 PST 2013


Author: eugenis
Date: Mon Feb 11 09:16:48 2013
New Revision: 174887

URL: http://llvm.org/viewvc/llvm-project?rev=174887&view=rev
Log:
[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.

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=174887&r1=174886&r2=174887&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Mon Feb 11 09:16:48 2013
@@ -157,7 +157,8 @@ INTERCEPTOR(int, vscanf, const char *for
   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 *st
   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,
   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;
 }

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc?rev=174887&r1=174886&r2=174887&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc Mon Feb 11 09:16:48 2013
@@ -15,10 +15,10 @@
 #include <stdarg.h>
 
 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(ScanfDir
 
 // 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, cons
     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);
   }
 }

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc?rev=174887&r1=174886&r2=174887&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc Mon Feb 11 09:16:48 2013
@@ -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<unsigned> 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);
 }





More information about the llvm-commits mailing list