summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-02-11 15:16:48 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2013-02-11 15:16:48 +0000
commit455c72d25eaa886b60df9a1fddb8951f1d6d950c (patch)
treeeb68e74e5d7f3af4c24eae4e07d542a4f87b5cfa
parentc5f44bc62de36161d6ed7dcbebc3fd2597f6f37a (diff)
downloadbcm5719-llvm-455c72d25eaa886b60df9a1fddb8951f1d6d950c.tar.gz
bcm5719-llvm-455c72d25eaa886b60df9a1fddb8951f1d6d950c.zip
[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
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc9
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc19
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc43
3 files changed, 51 insertions, 20 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 918c16ffd95..ba923e7ca4a 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 50ce70f9ad8..9ab5ae225fa 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 <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(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 1caf21dd9e5..91a65945091 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<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);
}
OpenPOWER on IntegriCloud