1 | // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 |
2 | // XFAIL: android |
3 | |
4 | // RUN: rm -rf %t-dir |
5 | // RUN: mkdir -p %t-dir |
6 | // |
7 | // RUN: %clangxx_asan -O0 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
8 | // RUN: %clangxx_asan -O1 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
9 | // RUN: %clangxx_asan -O2 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
10 | // RUN: %clangxx_asan -O3 %s -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
11 | // |
12 | // RUN: %clangxx_asan -O0 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
13 | // RUN: %clangxx_asan -O1 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
14 | // RUN: %clangxx_asan -O2 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
15 | // RUN: %clangxx_asan -O3 %s -D_FILE_OFFSET_BITS=64 -DTEMP_DIR='"'"%t-dir"'"' -o %t && %run %t 2>&1 | FileCheck %s |
16 | |
17 | #include <dirent.h> |
18 | #include <memory.h> |
19 | #include <stdio.h> |
20 | #include <stdlib.h> |
21 | #include <unistd.h> |
22 | |
23 | |
24 | int main() { |
25 | // Ensure the readdir_r interceptor doesn't erroneously mark the entire dirent |
26 | // as written when the end of the directory pointer is reached. |
27 | fputs("test1: reading the " TEMP_DIR " directory...\n" , stderr); |
28 | DIR *d = opendir(TEMP_DIR); |
29 | struct dirent *result = (struct dirent *)(0xfeedbeef); |
30 | // We assume the temp dir for this test doesn't have crazy long file names. |
31 | char entry_buffer[4096]; |
32 | memset(s: entry_buffer, c: 0xab, n: sizeof(entry_buffer)); |
33 | unsigned count = 0; |
34 | do { |
35 | // Stamp the entry struct to try to trick the interceptor. |
36 | ((struct dirent *)entry_buffer)->d_reclen = 9999; |
37 | if (readdir_r(dirp: d, entry: (struct dirent *)entry_buffer, result: &result) != 0) |
38 | abort(); |
39 | ++count; |
40 | } while (result != NULL); |
41 | fprintf(stderr, format: "read %d entries\n" , count); |
42 | closedir(dirp: d); |
43 | // CHECK: test1: reading the {{.*}} directory... |
44 | // CHECK-NOT: stack-buffer-overflow |
45 | // CHECK: read {{.*}} entries |
46 | |
47 | // Ensure the readdir64_r interceptor doesn't have the bug either. |
48 | fputs("test2: reading the " TEMP_DIR " directory...\n" , stderr); |
49 | d = opendir(TEMP_DIR); |
50 | struct dirent64 *result64; |
51 | memset(s: entry_buffer, c: 0xab, n: sizeof(entry_buffer)); |
52 | count = 0; |
53 | do { |
54 | // Stamp the entry struct to try to trick the interceptor. |
55 | ((struct dirent64 *)entry_buffer)->d_reclen = 9999; |
56 | if (readdir64_r(dirp: d, entry: (struct dirent64 *)entry_buffer, result: &result64) != 0) |
57 | abort(); |
58 | ++count; |
59 | } while (result64 != NULL); |
60 | fprintf(stderr, format: "read %d entries\n" , count); |
61 | closedir(dirp: d); |
62 | // CHECK: test2: reading the {{.*}} directory... |
63 | // CHECK-NOT: stack-buffer-overflow |
64 | // CHECK: read {{.*}} entries |
65 | } |
66 | |