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