aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2018-06-11 22:58:04 +0000
committerPeter Wu <peter@lekensteyn.nl>2018-06-11 22:58:04 +0000
commit552e9aa60773c7a936ded4a4cc2587e646ba15b9 (patch)
tree1986fb23f56928d6b5a9b82dfa6ff352fbc5c013 /test
parentf0762ed4b1a94a9d4f5fafabb41708cd1e09057f (diff)
[sanitizer] Add fgets, fputs and puts into sanitizer_common
Summary: Add fgets, fputs and puts to sanitizer_common. This adds ASAN coverage for these functions, extends MSAN support from fgets to fputs/puts and extends TSAN support from puts to fputs. Fixes: https://github.com/google/sanitizers/issues/952 Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D46545 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@334450 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/asan/TestCases/Posix/fgets_fputs.cc46
-rw-r--r--test/msan/fgets_fputs.cc47
-rw-r--r--test/sanitizer_common/TestCases/Posix/fgets.cc20
-rw-r--r--test/sanitizer_common/TestCases/Posix/fputs_puts.cc18
-rw-r--r--test/tsan/race_on_fputs.cc29
5 files changed, 160 insertions, 0 deletions
diff --git a/test/asan/TestCases/Posix/fgets_fputs.cc b/test/asan/TestCases/Posix/fgets_fputs.cc
new file mode 100644
index 000000000..6f0696393
--- /dev/null
+++ b/test/asan/TestCases/Posix/fgets_fputs.cc
@@ -0,0 +1,46 @@
+// RUN: %clangxx_asan -g %s -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-FGETS
+// RUN: not %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-FPUTS
+// RUN: not %run %t 3 3 2>&1 | FileCheck %s --check-prefix=CHECK-PUTS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int test_fgets() {
+ FILE *fp = fopen("/etc/passwd", "r");
+ char buf[2];
+ fgets(buf, sizeof(buf) + 1, fp); // BOOM
+ fclose(fp);
+ return 0;
+}
+
+int test_fputs() {
+ FILE *fp = fopen("/dev/null", "w");
+ char buf[1] = {'x'}; // Note: not nul-terminated
+ fputs(buf, fp); // BOOM
+ return fclose(fp);
+}
+
+void test_puts() {
+ char *p = strdup("x");
+ free(p);
+ puts(p); // BOOM
+}
+
+int main(int argc, char *argv[]) {
+ if (argc == 1)
+ test_fgets();
+ else if (argc == 2)
+ test_fputs();
+ else
+ test_puts();
+ return 0;
+}
+
+// CHECK-FGETS: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}}
+// CHECK-FGETS: #{{.*}} in {{(wrap_|__interceptor_)?}}fgets
+// CHECK-FPUTS: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}}
+// CHECK-FPUTS: #{{.*}} in {{(wrap_|__interceptor_)?}}fputs
+// CHECK-PUTS: {{.*ERROR: AddressSanitizer: heap-use-after-free}}
+// CHECK-PUTS: #{{.*}} in {{(wrap_|__interceptor_)?}}puts
diff --git a/test/msan/fgets_fputs.cc b/test/msan/fgets_fputs.cc
new file mode 100644
index 000000000..1e9694398
--- /dev/null
+++ b/test/msan/fgets_fputs.cc
@@ -0,0 +1,47 @@
+// RUN: %clangxx_msan -g %s -o %t
+// RUN: %run %t
+// RUN: not %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-FPUTS
+// RUN: not %run %t 3 3 2>&1 | FileCheck %s --check-prefix=CHECK-PUTS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int test_fgets() {
+ FILE *fp = fopen("/dev/zero", "r");
+ char c;
+
+ if (!fgets(&c, 1, fp))
+ return 1;
+
+ if (c == '1') // No error
+ return 2;
+
+ fclose(fp);
+ return 0;
+}
+
+int test_fputs() {
+ FILE *fp = fopen("/dev/null", "w");
+ char buf[2];
+ fputs(buf, fp); // BOOM
+ return fclose(fp);
+}
+
+void test_puts() {
+ char buf[2];
+ puts(buf); // BOOM
+}
+
+int main(int argc, char *argv[]) {
+ if (argc == 1)
+ test_fgets();
+ else if (argc == 2)
+ test_fputs();
+ else
+ test_puts();
+ return 0;
+}
+
+// CHECK-FPUTS: Uninitialized bytes in __interceptor_fputs at offset 0 inside
+// CHECK-PUTS: Uninitialized bytes in __interceptor_puts at offset 0 inside
diff --git a/test/sanitizer_common/TestCases/Posix/fgets.cc b/test/sanitizer_common/TestCases/Posix/fgets.cc
new file mode 100644
index 000000000..4eda4c1fc
--- /dev/null
+++ b/test/sanitizer_common/TestCases/Posix/fgets.cc
@@ -0,0 +1,20 @@
+// RUN: %clangxx -g %s -o %t && %run %t
+
+#include <stdio.h>
+
+int main(void) {
+ FILE *fp;
+ char buf[2];
+ char *s;
+
+ fp = fopen("/etc/passwd", "r");
+ if (!fp)
+ return 1;
+
+ s = fgets(buf, sizeof(buf), fp);
+ if (!s)
+ return 2;
+
+ fclose(fp);
+ return 0;
+}
diff --git a/test/sanitizer_common/TestCases/Posix/fputs_puts.cc b/test/sanitizer_common/TestCases/Posix/fputs_puts.cc
new file mode 100644
index 000000000..8e8f7d384
--- /dev/null
+++ b/test/sanitizer_common/TestCases/Posix/fputs_puts.cc
@@ -0,0 +1,18 @@
+// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s
+// CHECK: {{^foobar$}}
+
+#include <stdio.h>
+
+int main(void) {
+ int r;
+
+ r = fputs("foo", stdout);
+ if (r < 0)
+ return 1;
+
+ r = puts("bar");
+ if (r < 0)
+ return 1;
+
+ return 0;
+}
diff --git a/test/tsan/race_on_fputs.cc b/test/tsan/race_on_fputs.cc
new file mode 100644
index 000000000..53042e3d3
--- /dev/null
+++ b/test/tsan/race_on_fputs.cc
@@ -0,0 +1,29 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s
+#include "test.h"
+
+char s[] = "abracadabra";
+
+void *Thread0(void *p) {
+ fputs(s, stdout);
+ barrier_wait(&barrier);
+ return 0;
+}
+
+void *Thread1(void *p) {
+ barrier_wait(&barrier);
+ s[3] = 'z';
+ return 0;
+}
+
+int main() {
+ barrier_init(&barrier, 2);
+ pthread_t th[2];
+ pthread_create(&th[0], 0, Thread0, 0);
+ pthread_create(&th[1], 0, Thread1, 0);
+ pthread_join(th[0], 0);
+ pthread_join(th[1], 0);
+ fprintf(stderr, "DONE");
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: DONE