1*7c3d14c8STreehugger Robot // Test strict_string_checks option in strtol function
2*7c3d14c8STreehugger Robot // RUN: %clang_asan -D_CRT_SECURE_NO_WARNINGS -DTEST1 %s -o %t
3*7c3d14c8STreehugger Robot // RUN: %run %t test1 2>&1
4*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=false %run %t test1 2>&1
5*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=true not %run %t test1 2>&1 | FileCheck %s --check-prefix=CHECK1
6*7c3d14c8STreehugger Robot // RUN: %run %t test2 2>&1
7*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=false %run %t test2 2>&1
8*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=true not %run %t test2 2>&1 | FileCheck %s --check-prefix=CHECK2
9*7c3d14c8STreehugger Robot // RUN: %run %t test3 2>&1
10*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=false %run %t test3 2>&1
11*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=true not %run %t test3 2>&1 | FileCheck %s --check-prefix=CHECK3
12*7c3d14c8STreehugger Robot // RUN: %run %t test4 2>&1
13*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=false %run %t test4 2>&1
14*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=true not %run %t test4 2>&1 | FileCheck %s --check-prefix=CHECK4
15*7c3d14c8STreehugger Robot // RUN: %run %t test5 2>&1
16*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=false %run %t test5 2>&1
17*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=true not %run %t test5 2>&1 | FileCheck %s --check-prefix=CHECK5
18*7c3d14c8STreehugger Robot // RUN: %run %t test6 2>&1
19*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=false %run %t test6 2>&1
20*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=true not %run %t test6 2>&1 | FileCheck %s --check-prefix=CHECK6
21*7c3d14c8STreehugger Robot // RUN: %run %t test7 2>&1
22*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=false %run %t test7 2>&1
23*7c3d14c8STreehugger Robot // RUN: %env_asan_opts=strict_string_checks=true not %run %t test7 2>&1 | FileCheck %s --check-prefix=CHECK7
24*7c3d14c8STreehugger Robot
25*7c3d14c8STreehugger Robot #include <assert.h>
26*7c3d14c8STreehugger Robot #include <stdlib.h>
27*7c3d14c8STreehugger Robot #include <string.h>
28*7c3d14c8STreehugger Robot #include <stdio.h>
29*7c3d14c8STreehugger Robot #include <sanitizer/asan_interface.h>
30*7c3d14c8STreehugger Robot
test1(char * array,char * endptr)31*7c3d14c8STreehugger Robot void test1(char *array, char *endptr) {
32*7c3d14c8STreehugger Robot // Buffer overflow if there is no terminating null (depends on base)
33*7c3d14c8STreehugger Robot long r = strtol(array, &endptr, 3);
34*7c3d14c8STreehugger Robot assert(array + 2 == endptr);
35*7c3d14c8STreehugger Robot assert(r == 5);
36*7c3d14c8STreehugger Robot }
37*7c3d14c8STreehugger Robot
test2(char * array,char * endptr)38*7c3d14c8STreehugger Robot void test2(char *array, char *endptr) {
39*7c3d14c8STreehugger Robot // Buffer overflow if there is no terminating null (depends on base)
40*7c3d14c8STreehugger Robot array[2] = 'z';
41*7c3d14c8STreehugger Robot long r = strtol(array, &endptr, 35);
42*7c3d14c8STreehugger Robot assert(array + 2 == endptr);
43*7c3d14c8STreehugger Robot assert(r == 37);
44*7c3d14c8STreehugger Robot }
45*7c3d14c8STreehugger Robot
test3(char * array,char * endptr)46*7c3d14c8STreehugger Robot void test3(char *array, char *endptr) {
47*7c3d14c8STreehugger Robot #ifdef _MSC_VER
48*7c3d14c8STreehugger Robot // Using -1 for a strtol base causes MSVC to abort. Print the expected lines
49*7c3d14c8STreehugger Robot // to make the test pass.
50*7c3d14c8STreehugger Robot fprintf(stderr, "ERROR: AddressSanitizer: use-after-poison on address\n");
51*7c3d14c8STreehugger Robot fprintf(stderr, "READ of size 1\n");
52*7c3d14c8STreehugger Robot fflush(stderr);
53*7c3d14c8STreehugger Robot char *opts = getenv("ASAN_OPTIONS");
54*7c3d14c8STreehugger Robot exit(opts && strstr(opts, "strict_string_checks=true"));
55*7c3d14c8STreehugger Robot #endif
56*7c3d14c8STreehugger Robot // Buffer overflow if base is invalid.
57*7c3d14c8STreehugger Robot memset(array, 0, 8);
58*7c3d14c8STreehugger Robot ASAN_POISON_MEMORY_REGION(array, 8);
59*7c3d14c8STreehugger Robot long r = strtol(array + 1, NULL, -1);
60*7c3d14c8STreehugger Robot assert(r == 0);
61*7c3d14c8STreehugger Robot ASAN_UNPOISON_MEMORY_REGION(array, 8);
62*7c3d14c8STreehugger Robot }
63*7c3d14c8STreehugger Robot
test4(char * array,char * endptr)64*7c3d14c8STreehugger Robot void test4(char *array, char *endptr) {
65*7c3d14c8STreehugger Robot #ifdef _MSC_VER
66*7c3d14c8STreehugger Robot // Using -1 for a strtol base causes MSVC to abort. Print the expected lines
67*7c3d14c8STreehugger Robot // to make the test pass.
68*7c3d14c8STreehugger Robot fprintf(stderr, "ERROR: AddressSanitizer: heap-buffer-overflow on address\n");
69*7c3d14c8STreehugger Robot fprintf(stderr, "READ of size 1\n");
70*7c3d14c8STreehugger Robot fflush(stderr);
71*7c3d14c8STreehugger Robot char *opts = getenv("ASAN_OPTIONS");
72*7c3d14c8STreehugger Robot exit(opts && strstr(opts, "strict_string_checks=true"));
73*7c3d14c8STreehugger Robot #endif
74*7c3d14c8STreehugger Robot // Buffer overflow if base is invalid.
75*7c3d14c8STreehugger Robot long r = strtol(array + 3, NULL, 1);
76*7c3d14c8STreehugger Robot assert(r == 0);
77*7c3d14c8STreehugger Robot }
78*7c3d14c8STreehugger Robot
test5(char * array,char * endptr)79*7c3d14c8STreehugger Robot void test5(char *array, char *endptr) {
80*7c3d14c8STreehugger Robot // Overflow if no digits are found.
81*7c3d14c8STreehugger Robot array[0] = ' ';
82*7c3d14c8STreehugger Robot array[1] = '+';
83*7c3d14c8STreehugger Robot array[2] = '-';
84*7c3d14c8STreehugger Robot long r = strtol(array, NULL, 0);
85*7c3d14c8STreehugger Robot assert(r == 0);
86*7c3d14c8STreehugger Robot }
87*7c3d14c8STreehugger Robot
test6(char * array,char * endptr)88*7c3d14c8STreehugger Robot void test6(char *array, char *endptr) {
89*7c3d14c8STreehugger Robot // Overflow if no digits are found.
90*7c3d14c8STreehugger Robot array[0] = ' ';
91*7c3d14c8STreehugger Robot array[1] = array[2] = 'z';
92*7c3d14c8STreehugger Robot long r = strtol(array, &endptr, 0);
93*7c3d14c8STreehugger Robot assert(array == endptr);
94*7c3d14c8STreehugger Robot assert(r == 0);
95*7c3d14c8STreehugger Robot }
96*7c3d14c8STreehugger Robot
test7(char * array,char * endptr)97*7c3d14c8STreehugger Robot void test7(char *array, char *endptr) {
98*7c3d14c8STreehugger Robot // Overflow if no digits are found.
99*7c3d14c8STreehugger Robot array[2] = 'z';
100*7c3d14c8STreehugger Robot long r = strtol(array + 2, NULL, 0);
101*7c3d14c8STreehugger Robot assert(r == 0);
102*7c3d14c8STreehugger Robot }
103*7c3d14c8STreehugger Robot
main(int argc,char ** argv)104*7c3d14c8STreehugger Robot int main(int argc, char **argv) {
105*7c3d14c8STreehugger Robot char *array0 = (char*)malloc(11);
106*7c3d14c8STreehugger Robot char* array = array0 + 8;
107*7c3d14c8STreehugger Robot char *endptr = NULL;
108*7c3d14c8STreehugger Robot array[0] = '1';
109*7c3d14c8STreehugger Robot array[1] = '2';
110*7c3d14c8STreehugger Robot array[2] = '3';
111*7c3d14c8STreehugger Robot if (argc != 2) return 1;
112*7c3d14c8STreehugger Robot if (!strcmp(argv[1], "test1")) test1(array, endptr);
113*7c3d14c8STreehugger Robot // CHECK1: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
114*7c3d14c8STreehugger Robot // CHECK1: READ of size 4
115*7c3d14c8STreehugger Robot if (!strcmp(argv[1], "test2")) test2(array, endptr);
116*7c3d14c8STreehugger Robot // CHECK2: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
117*7c3d14c8STreehugger Robot // CHECK2: READ of size 4
118*7c3d14c8STreehugger Robot if (!strcmp(argv[1], "test3")) test3(array0, endptr);
119*7c3d14c8STreehugger Robot // CHECK3: {{.*ERROR: AddressSanitizer: use-after-poison on address}}
120*7c3d14c8STreehugger Robot // CHECK3: READ of size 1
121*7c3d14c8STreehugger Robot if (!strcmp(argv[1], "test4")) test4(array, endptr);
122*7c3d14c8STreehugger Robot // CHECK4: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
123*7c3d14c8STreehugger Robot // CHECK4: READ of size 1
124*7c3d14c8STreehugger Robot if (!strcmp(argv[1], "test5")) test5(array, endptr);
125*7c3d14c8STreehugger Robot // CHECK5: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
126*7c3d14c8STreehugger Robot // CHECK5: READ of size 4
127*7c3d14c8STreehugger Robot if (!strcmp(argv[1], "test6")) test6(array, endptr);
128*7c3d14c8STreehugger Robot // CHECK6: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
129*7c3d14c8STreehugger Robot // CHECK6: READ of size 4
130*7c3d14c8STreehugger Robot if (!strcmp(argv[1], "test7")) test7(array, endptr);
131*7c3d14c8STreehugger Robot // CHECK7: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
132*7c3d14c8STreehugger Robot // CHECK7: READ of size 2
133*7c3d14c8STreehugger Robot free(array0);
134*7c3d14c8STreehugger Robot return 0;
135*7c3d14c8STreehugger Robot }
136