[sanitizer] Fix handling of %n in scanf interceptor.

%n does not increase the input item count. The new code emits writes to %n
arguments even if it has run out of input items.


git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@188069 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc b/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
index 8bb5cd8..08752e6 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc
@@ -278,7 +278,7 @@
   CHECK_GT(n_inputs, 0);
   const char *p = format;
 
-  while (*p && n_inputs) {
+  while (*p) {
     ScanfDirective dir;
     p = scanf_parse_next(p, allowGnuMalloc, &dir);
     if (!p)
@@ -301,6 +301,8 @@
     void *argp = va_arg(aq, void *);
     if (dir.convSpecifier != 'n')
       --n_inputs;
+    if (n_inputs < 0)
+      break;
     if (size == SSS_STRLEN) {
       size = internal_strlen((const char *)argp) + 1;
     }
diff --git a/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc b/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc
index 1df2bcf..e035406 100644
--- a/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_scanf_interceptor_test.cc
@@ -169,7 +169,7 @@
   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 //1\n", 1, 3, I, I, 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);