[Sanitizer] Teach ReadFileToBuffer to distinguish empty file from inaccessible file.
authorAlexey Samsonov <vonosmas@gmail.com>
Fri, 17 Jul 2015 23:50:08 +0000 (23:50 +0000)
committerAlexey Samsonov <vonosmas@gmail.com>
Fri, 17 Jul 2015 23:50:08 +0000 (23:50 +0000)
Summary:
This fixes https://code.google.com/p/address-sanitizer/issues/detail?id=399
(sanitizers crash with empty suppression files).

Reviewers: kcc

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D11284

llvm-svn: 242594

compiler-rt/lib/sanitizer_common/sanitizer_common.cc
compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/sanitizer_flags.cc
compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cc
compiler-rt/lib/sanitizer_common/sanitizer_procmaps_linux.cc
compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
compiler-rt/test/lsan/TestCases/suppressions_file.cc

index d14e988..541308c 100644 (file)
@@ -140,40 +140,40 @@ void NORETURN CheckFailed(const char *file, int line, const char *cond,
   Die();
 }
 
-uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
-                      uptr max_len, error_t *errno_p) {
+bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
+                      uptr *read_len, uptr max_len, error_t *errno_p) {
   uptr PageSize = GetPageSizeCached();
   uptr kMinFileLen = PageSize;
-  uptr read_len = 0;
-  *buff = 0;
+  *buff = nullptr;
   *buff_size = 0;
+  *read_len = 0;
   // The files we usually open are not seekable, so try different buffer sizes.
   for (uptr size = kMinFileLen; size <= max_len; size *= 2) {
     fd_t fd = OpenFile(file_name, RdOnly, errno_p);
-    if (fd == kInvalidFd) return 0;
+    if (fd == kInvalidFd) return false;
     UnmapOrDie(*buff, *buff_size);
     *buff = (char*)MmapOrDie(size, __func__);
     *buff_size = size;
+    *read_len = 0;
     // Read up to one page at a time.
-    read_len = 0;
     bool reached_eof = false;
-    while (read_len + PageSize <= size) {
+    while (*read_len + PageSize <= size) {
       uptr just_read;
-      if (!ReadFromFile(fd, *buff + read_len, PageSize, &just_read, errno_p)) {
+      if (!ReadFromFile(fd, *buff + *read_len, PageSize, &just_read, errno_p)) {
         UnmapOrDie(*buff, *buff_size);
-        return 0;
+        return false;
       }
       if (just_read == 0) {
         reached_eof = true;
         break;
       }
-      read_len += just_read;
+      *read_len += just_read;
     }
     CloseFile(fd);
     if (reached_eof)  // We've read the whole file.
       break;
   }
-  return read_len;
+  return true;
 }
 
 typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
index b97086f..20b841c 100644 (file)
@@ -228,10 +228,12 @@ bool SupportsColoredOutput(fd_t fd);
 
 // Opens the file 'file_name" and reads up to 'max_len' bytes.
 // The resulting buffer is mmaped and stored in '*buff'.
-// The size of the mmaped region is stored in '*buff_size',
-// Returns the number of read bytes or 0 if file can not be opened.
-uptr ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
-                      uptr max_len, error_t *errno_p = nullptr);
+// The size of the mmaped region is stored in '*buff_size'.
+// The total number of read bytes is stored in '*read_len'.
+// Returns true if file was successfully opened and read.
+bool ReadFileToBuffer(const char *file_name, char **buff, uptr *buff_size,
+                      uptr *read_len, uptr max_len = 1 << 26,
+                      error_t *errno_p = nullptr);
 // Maps given file to virtual memory, and returns pointer to it
 // (or NULL if mapping fails). Stores the size of mmaped region
 // in '*buff_size'.
index 01098a3..5d9b299 100644 (file)
@@ -54,11 +54,10 @@ class FlagHandlerInclude : public FlagHandlerBase {
   bool Parse(const char *value) final {
     char *data;
     uptr data_mapped_size;
+    uptr len;
     error_t err;
-    uptr len =
-      ReadFileToBuffer(value, &data, &data_mapped_size,
-                       Max(kMaxIncludeSize, GetPageSizeCached()), &err);
-    if (!len) {
+    if (!ReadFileToBuffer(value, &data, &data_mapped_size, &len,
+                          Max(kMaxIncludeSize, GetPageSizeCached()), &err)) {
       Printf("Failed to read options from '%s': error %d\n", value, err);
       return false;
     }
index 7141bcd..533146a 100644 (file)
@@ -375,8 +375,8 @@ const char *GetEnv(const char *name) {
   if (!inited) {
     inited = true;
     uptr environ_size;
-    len = ReadFileToBuffer("/proc/self/environ",
-                           &environ, &environ_size, 1 << 26);
+    if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len))
+      environ = nullptr;
   }
   if (!environ || len == 0) return 0;
   uptr namelen = internal_strlen(name);
@@ -405,9 +405,13 @@ extern "C" {
 static void ReadNullSepFileToArray(const char *path, char ***arr,
                                    int arr_size) {
   char *buff;
-  uptr buff_size = 0;
+  uptr buff_size;
+  uptr buff_len;
   *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
-  ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
+  if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) {
+    (*arr)[0] = nullptr;
+    return;
+  }
   (*arr)[0] = buff;
   int count, i;
   for (count = 1, i = 1; ; i++) {
@@ -418,7 +422,7 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
       count++;
     }
   }
-  (*arr)[count] = 0;
+  (*arr)[count] = nullptr;
 }
 #endif
 
index 2c6ce8e..4ddf786 100644 (file)
@@ -153,8 +153,9 @@ uptr MemoryMappingLayout::DumpListOfModules(LoadedModule *modules,
 void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {
   char *smaps = 0;
   uptr smaps_cap = 0;
-  uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",
-      &smaps, &smaps_cap, 64<<20);
+  uptr smaps_len = 0;
+  if (!ReadFileToBuffer("/proc/self/smaps", &smaps, &smaps_cap, &smaps_len))
+    return;
   uptr start = 0;
   bool file = false;
   const char *pos = smaps;
index 79ca4df..0e97f96 100644 (file)
@@ -18,8 +18,8 @@
 namespace __sanitizer {
 
 void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
-  proc_maps->len = ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
-                                    &proc_maps->mmaped_size, 1 << 26);
+  CHECK(ReadFileToBuffer("/proc/self/maps", &proc_maps->data,
+                         &proc_maps->mmaped_size, &proc_maps->len));
 }
 
 static bool IsOneOf(char c, char c1, char c2) {
index 08cb497..5e0cce1 100644 (file)
@@ -60,15 +60,13 @@ void SuppressionContext::ParseFromFile(const char *filename) {
   }
 
   // Read the file.
-  char *file_contents;
-  uptr buffer_size;
-  const uptr max_len = 1 << 26;
-  uptr contents_size =
-    ReadFileToBuffer(filename, &file_contents, &buffer_size, max_len);
   VPrintf(1, "%s: reading suppressions file at %s\n",
           SanitizerToolName, filename);
-
-  if (contents_size == 0) {
+  char *file_contents;
+  uptr buffer_size;
+  uptr contents_size;
+  if (!ReadFileToBuffer(filename, &file_contents, &buffer_size,
+                        &contents_size)) {
     Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
            filename);
     Die();
index d030896..805091c 100644 (file)
@@ -1,6 +1,10 @@
 // RUN: LSAN_BASE="use_registers=0:use_stacks=0"
 // RUN: %clangxx_lsan %s -o %t
 
+// RUN: rm -f %t.supp
+// RUN: touch %t.supp
+// RUN: LSAN_OPTIONS="$LSAN_BASE:suppressions='%t.supp'" not %run %t 2>&1 | FileCheck %s --check-prefix=NOSUPP
+
 // RUN: echo "leak:*LSanTestLeakingFunc*" > %t.supp
 // RUN: LSAN_OPTIONS="$LSAN_BASE:suppressions='%t.supp'" not %run %t 2>&1 | FileCheck %s
 
@@ -24,3 +28,5 @@ int main() {
 // CHECK: Suppressions used:
 // CHECK: 1 666 *LSanTestLeakingFunc*
 // CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: 1337 byte(s) leaked in 1 allocation(s)
+
+// NOSUPP: SUMMARY: {{(Leak|Address)}}Sanitizer: 2003 byte(s) leaked in 2 allocation(s).