1909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// Test strict_string_checks option in strncat function
2909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// RUN: %clang_asan %s -o %t
3909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// RUN: not %run %t test1 2>&1 | FileCheck %s --check-prefix=CHECK1-NONSTRICT --check-prefix=CHECK1
4909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// RUN: ASAN_OPTIONS=strict_string_checks=false not  %run %t test1 2>&1 | FileCheck %s --check-prefix=CHECK1-NONSTRICT --check-prefix=CHECK1
5909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// RUN: ASAN_OPTIONS=strict_string_checks=true not %run %t test1 2>&1 | FileCheck %s --check-prefix=CHECK1-STRICT --check-prefix=CHECK1
6909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// RUN: not %run %t test2 2>&1 | FileCheck %s --check-prefix=CHECK2-NONSTRICT --check-prefix=CHECK2
7909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// RUN: ASAN_OPTIONS=strict_string_checks=false not  %run %t test2 2>&1 | FileCheck %s --check-prefix=CHECK2-NONSTRICT --check-prefix=CHECK2
8909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar// RUN: ASAN_OPTIONS=strict_string_checks=true not %run %t test2 2>&1 | FileCheck %s --check-prefix=CHECK2-STRICT --check-prefix=CHECK2
9909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
10909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#include <assert.h>
11909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#include <stdlib.h>
12909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar#include <string.h>
13909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
14909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarvoid test1(char *to, int to_size, char *from) {
15909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // One of arguments points to not allocated memory.
16909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  char* r = strncat(to + to_size, from, 2);
17909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar}
18909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
19909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarvoid test2(char *to, int to_size, char *from) {
20909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // "to" is not zero-terminated.
21909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  memset(to, 'z', to_size);
22909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  char* r = strncat(to, from, 1);
23909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar}
24909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar
25909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainarint main(int argc, char **argv) {
26909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  size_t to_size = 100;
27909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  char *to = (char*)malloc(to_size);
28909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  size_t from_size = 20;
29909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  char *from = (char*)malloc(from_size);
30909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  memset(from, 'z', from_size);
31909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  from[from_size - 1] = '\0';
32909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  if (argc != 2) return 1;
33909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  if (!strcmp(argv[1], "test1")) test1(to, to_size, from);
34909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // CHECK1: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
35909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // CHECK1-STRICT: READ of size 1
36909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // CHECK1-NONSTRICT: WRITE of size 3
37909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  if (!strcmp(argv[1], "test2")) test2(to, to_size, from);
38909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // CHECK2: {{.*ERROR: AddressSanitizer: heap-buffer-overflow on address}}
39909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // CHECK2-STRICT: READ of size 101
40909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  // CHECK2-NONSTRICT: WRITE of size 2
41909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  free(to);
42909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  free(from);
43909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar  return 0;
44909fff81b83df049ecc6e02407394640435d7befPirama Arumuga Nainar}
45