1 | // RUN: %clang_asan %s -o %t |
2 | |
3 | // Test overflows with strict_string_checks |
4 | |
5 | // RUN: %env_asan_opts=strict_string_checks=true not %run %t test1 2>&1 | \ |
6 | // RUN: FileCheck %s --check-prefix=CHECK1 |
7 | // RUN: %env_asan_opts=intercept_strtok=false %run %t test1 2>&1 |
8 | // RUN: %env_asan_opts=strict_string_checks=true not %run %t test2 2>&1 | \ |
9 | // RUN: FileCheck %s --check-prefix=CHECK2 |
10 | // RUN: %env_asan_opts=intercept_strtok=false %run %t test2 2>&1 |
11 | // RUN: %env_asan_opts=strict_string_checks=true not %run %t test3 2>&1 | \ |
12 | // RUN: FileCheck %s --check-prefix=CHECK3 |
13 | // RUN: %env_asan_opts=intercept_strtok=false %run %t test3 2>&1 |
14 | // RUN: %env_asan_opts=strict_string_checks=true %run %t test4 2>&1 |
15 | // RUN: %env_asan_opts=intercept_strtok=false %run %t test4 2>&1 |
16 | |
17 | // Test overflows with !strict_string_checks |
18 | // RUN: %env_asan_opts=strict_string_checks=false not %run %t test5 2>&1 | \ |
19 | // RUN: FileCheck %s --check-prefix=CHECK5 |
20 | // RUN: %env_asan_opts=intercept_strtok=false %run %t test5 2>&1 |
21 | // RUN: %env_asan_opts=strict_string_checks=false not %run %t test6 2>&1 | \ |
22 | // RUN: FileCheck %s --check-prefix=CHECK6 |
23 | // RUN: %env_asan_opts=intercept_strtok=false %run %t test6 2>&1 |
24 | |
25 | |
26 | #include <assert.h> |
27 | #include <string.h> |
28 | #include <sanitizer/asan_interface.h> |
29 | |
30 | // Check that we find overflows in the delimiters on the first call |
31 | // with strict_string_checks. |
32 | void test1() { |
33 | char *token; |
34 | char s[4] = "abc" ; |
35 | char token_delimiter[2] = "b" ; |
36 | __asan_poison_memory_region (addr: (char *)&token_delimiter[1], size: 2); |
37 | token = strtok(s: s, delim: token_delimiter); |
38 | // CHECK1: 'token_delimiter'{{.*}} <== Memory access at offset {{[0-9]+}} partially overflows this variable |
39 | } |
40 | |
41 | // Check that we find overflows in the delimiters on the second call (str == NULL) |
42 | // with strict_string_checks. |
43 | void test2() { |
44 | char *token; |
45 | char s[4] = "abc" ; |
46 | char token_delimiter[2] = "b" ; |
47 | token = strtok(s: s, delim: token_delimiter); |
48 | assert(strcmp(token, "a" ) == 0); |
49 | __asan_poison_memory_region (addr: (char *)&token_delimiter[1], size: 2); |
50 | token = strtok(NULL, delim: token_delimiter); |
51 | // CHECK2: 'token_delimiter'{{.*}} <== Memory access at offset {{[0-9]+}} partially overflows this variable |
52 | } |
53 | |
54 | // Check that we find overflows in the string (only on the first call) with strict_string_checks. |
55 | void test3() { |
56 | char *token; |
57 | char s[4] = "abc" ; |
58 | char token_delimiter[2] = "b" ; |
59 | __asan_poison_memory_region (addr: (char *)&s[3], size: 2); |
60 | token = strtok(s: s, delim: token_delimiter); |
61 | // CHECK3: 's'{{.*}} <== Memory access at offset {{[0-9]+}} partially overflows this variable |
62 | } |
63 | |
64 | // Check that we do not crash when strtok returns NULL with strict_string_checks. |
65 | void test4() { |
66 | char *token; |
67 | char s[] = "" ; |
68 | char token_delimiter[] = "a" ; |
69 | token = strtok(s: s, delim: token_delimiter); |
70 | assert(token == NULL); |
71 | } |
72 | |
73 | // Check that we find overflows in the string (only on the first call) with !strict_string_checks. |
74 | void test5() { |
75 | char *token; |
76 | char s[4] = "abc" ; |
77 | char token_delimiter[2] = "d" ; |
78 | __asan_poison_memory_region (addr: (char *)&s[2], size: 2); |
79 | __asan_poison_memory_region (addr: (char *)&token_delimiter[1], size: 2); |
80 | token = strtok(s: s, delim: token_delimiter); |
81 | // CHECK5: 's'{{.*}} <== Memory access at offset {{[0-9]+}} partially overflows this variable |
82 | } |
83 | |
84 | // Check that we find overflows in the delimiters (only on the first call) with !strict_string_checks. |
85 | void test6() { |
86 | char *token; |
87 | char s[4] = "abc" ; |
88 | char token_delimiter[1] = {'d'}; |
89 | __asan_poison_memory_region (addr: (char *)&token_delimiter[1], size: 2); |
90 | token = strtok(s: s, delim: &token_delimiter[1]); |
91 | // CHECK6: 'token_delimiter'{{.*}} <== Memory access at offset {{[0-9]+}} overflows this variable |
92 | } |
93 | |
94 | int main(int argc, char **argv) { |
95 | if (argc != 2) return 1; |
96 | if (!strcmp(s1: argv[1], s2: "test1" )) test1(); |
97 | if (!strcmp(s1: argv[1], s2: "test2" )) test2(); |
98 | if (!strcmp(s1: argv[1], s2: "test3" )) test3(); |
99 | if (!strcmp(s1: argv[1], s2: "test4" )) test4(); |
100 | if (!strcmp(s1: argv[1], s2: "test5" )) test5(); |
101 | if (!strcmp(s1: argv[1], s2: "test6" )) test6(); |
102 | return 0; |
103 | } |
104 | |