Sanitize printf functions.
Intercept and sanitize arguments passed to printf functions in ASan and TSan
(don't do this in MSan for now). The checks are controlled by runtime flag
(off by default for now).
Patch http://llvm-reviews.chandlerc.com/D2480 by Yuri Gribov!
llvm-svn: 199729
diff --git a/compiler-rt/lib/asan/lit_tests/TestCases/printf-1.c b/compiler-rt/lib/asan/lit_tests/TestCases/printf-1.c
new file mode 100644
index 0000000..1da5200
--- /dev/null
+++ b/compiler-rt/lib/asan/lit_tests/TestCases/printf-1.c
@@ -0,0 +1,16 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=check_printf=1 %t 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=check_printf=0 %t 2>&1 | FileCheck %s
+// RUN: %t 2>&1 | FileCheck %s
+
+#include <stdio.h>
+int main() {
+ volatile char c = '0';
+ volatile int x = 12;
+ volatile float f = 1.239;
+ volatile char s[] = "34";
+ printf("%c %d %.3f %s\n", c, x, f, s);
+ return 0;
+ // Check that printf works fine under Asan.
+ // CHECK: 0 12 1.239 34
+}
diff --git a/compiler-rt/lib/asan/lit_tests/TestCases/printf-2.c b/compiler-rt/lib/asan/lit_tests/TestCases/printf-2.c
new file mode 100644
index 0000000..960c818
--- /dev/null
+++ b/compiler-rt/lib/asan/lit_tests/TestCases/printf-2.c
@@ -0,0 +1,22 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=check_printf=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-ON %s
+// RUN: ASAN_OPTIONS=check_printf=0 %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+// RUN: %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+int main() {
+ volatile char c = '0';
+ volatile int x = 12;
+ volatile float f = 1.239;
+ volatile char s[] = "34";
+ char *p = strdup((const char *)s);
+ free(p);
+ printf("%c %d %.3f %s\n", c, x, f, p);
+ return 0;
+ // Check that %s is sanitized.
+ // CHECK-ON: heap-use-after-free
+ // CHECK-ON-NOT: 0 12 1.239 34
+ // CHECK-OFF: 0 12 1.239
+}
diff --git a/compiler-rt/lib/asan/lit_tests/TestCases/printf-3.c b/compiler-rt/lib/asan/lit_tests/TestCases/printf-3.c
new file mode 100644
index 0000000..12ecc64
--- /dev/null
+++ b/compiler-rt/lib/asan/lit_tests/TestCases/printf-3.c
@@ -0,0 +1,19 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=check_printf=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-ON %s
+// RUN: ASAN_OPTIONS=check_printf=0 %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+// RUN: %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+
+#include <stdio.h>
+int main() {
+ volatile char c = '0';
+ volatile int x = 12;
+ volatile float f = 1.239;
+ volatile char s[] = "34";
+ volatile int n[1];
+ printf("%c %d %.3f %s%n\n", c, x, f, s, &n[1]);
+ return 0;
+ // Check that %n is sanitized.
+ // CHECK-ON: stack-buffer-overflow
+ // CHECK-ON-NOT: 0 12 1.239 34
+ // CHECK-OFF: 0 12 1.239 34
+}
diff --git a/compiler-rt/lib/asan/lit_tests/TestCases/printf-4.c b/compiler-rt/lib/asan/lit_tests/TestCases/printf-4.c
new file mode 100644
index 0000000..970b7c6
--- /dev/null
+++ b/compiler-rt/lib/asan/lit_tests/TestCases/printf-4.c
@@ -0,0 +1,20 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=check_printf=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-ON %s
+// RUN: ASAN_OPTIONS=check_printf=0 %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+// RUN: %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+
+#include <stdio.h>
+int main() {
+ volatile char c = '0';
+ volatile int x = 12;
+ volatile float f = 1.239;
+ volatile char s[] = "34";
+ volatile char buf[2];
+ sprintf((char *)buf, "%c %d %.3f %s\n", c, x, f, s);
+ puts((const char *)buf);
+ return 0;
+ // Check that size of output buffer is sanitized.
+ // CHECK-ON: stack-buffer-overflow
+ // CHECK-ON-NOT: 0 12 1.239 34
+ // CHECK-OFF: 0 12 1.239 34
+}
diff --git a/compiler-rt/lib/asan/lit_tests/TestCases/printf-5.c b/compiler-rt/lib/asan/lit_tests/TestCases/printf-5.c
new file mode 100644
index 0000000..52760a5
--- /dev/null
+++ b/compiler-rt/lib/asan/lit_tests/TestCases/printf-5.c
@@ -0,0 +1,21 @@
+// RUN: %clang_asan -O2 %s -o %t
+// RUN: ASAN_OPTIONS=check_printf=1 not %t 2>&1 | FileCheck --check-prefix=CHECK-ON %s
+// RUN: ASAN_OPTIONS=check_printf=0 %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+// RUN: %t 2>&1 | FileCheck --check-prefix=CHECK-OFF %s
+
+#include <stdio.h>
+#include <string.h>
+int main() {
+ volatile char c = '0';
+ volatile int x = 12;
+ volatile float f = 1.239;
+ volatile char s[] = "34";
+ volatile char fmt[2];
+ memcpy((char *)fmt, "%c %d %f %s\n", sizeof(fmt));
+ printf(fmt, c, x, f, s);
+ return 0;
+ // Check that format string is sanitized.
+ // CHECK-ON: stack-buffer-overflow
+ // CHECK-ON-NOT: 0 12 1.239 34
+ // CHECK-OFF: 0
+}