1 // Test strict_string_checks option in strcat function 2 // RUN: %clang_asan %s -o %t 3 // RUN: not %run %t test1 2>&1 | FileCheck %s --check-prefix=CHECK1-NONSTRICT --check-prefix=CHECK1 4 // RUN: %env_asan_opts=strict_string_checks=false not %run %t test1 2>&1 | FileCheck %s --check-prefix=CHECK1-NONSTRICT --check-prefix=CHECK1 5 // RUN: %env_asan_opts=strict_string_checks=true not %run %t test1 2>&1 | FileCheck %s --check-prefix=CHECK1-STRICT --check-prefix=CHECK1 6 // RUN: not %run %t test2 2>&1 | FileCheck %s --check-prefix=CHECK2-NONSTRICT --check-prefix=CHECK2 7 // RUN: %env_asan_opts=strict_string_checks=false not %run %t test2 2>&1 | FileCheck %s --check-prefix=CHECK2-NONSTRICT --check-prefix=CHECK2 8 // RUN: %env_asan_opts=strict_string_checks=true not %run %t test2 2>&1 | FileCheck %s --check-prefix=CHECK2-STRICT --check-prefix=CHECK2 9 10 #include <assert.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 void test1(char *to, int to_size, char *from) { 15 // One of arguments points to not allocated memory. 16 char* r = strcat(to + to_size, from); 17 } 18 19 void test2(char *to, int to_size, char *from) { 20 // "to" is not zero-terminated. 21 memset(to, 'z', to_size); 22 char* r = strcat(to, from); 23 } 24 25 int main(int argc, char **argv) { 26 size_t to_size = 100; 27 char *to = (char*)malloc(to_size); 28 size_t from_size = 20; 29 char *from = (char*)malloc(from_size); 30 memset(from, 'z', from_size); 31 from[from_size - 1] = '\0'; 32 if (argc != 2) return 1; 33 if (!strcmp(argv[1], "test1")) test1(to, to_size, from); 34 // CHECK1: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}} 35 // CHECK1-STRICT: READ of size 1 36 // CHECK1-NONSTRICT: WRITE of size 20 37 if (!strcmp(argv[1], "test2")) test2(to, to_size, from); 38 // CHECK2: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}} 39 // CHECK2-STRICT: READ of size 101 40 // CHECK2-NONSTRICT: WRITE of size 20 41 free(to); 42 free(from); 43 return 0; 44 } 45