diff options
author | Peter Wu <peter@lekensteyn.nl> | 2018-06-11 22:58:04 +0000 |
---|---|---|
committer | Peter Wu <peter@lekensteyn.nl> | 2018-06-11 22:58:04 +0000 |
commit | 552e9aa60773c7a936ded4a4cc2587e646ba15b9 (patch) | |
tree | 1986fb23f56928d6b5a9b82dfa6ff352fbc5c013 /test | |
parent | f0762ed4b1a94a9d4f5fafabb41708cd1e09057f (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.cc | 46 | ||||
-rw-r--r-- | test/msan/fgets_fputs.cc | 47 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Posix/fgets.cc | 20 | ||||
-rw-r--r-- | test/sanitizer_common/TestCases/Posix/fputs_puts.cc | 18 | ||||
-rw-r--r-- | test/tsan/race_on_fputs.cc | 29 |
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 |