Merge pull request #121 from haberman/fuzz-fixes

Several fuzz fixes.
diff --git a/src/bloaty.cc b/src/bloaty.cc
index 9887529..025f5be 100644
--- a/src/bloaty.cc
+++ b/src/bloaty.cc
@@ -874,10 +874,10 @@
 uint64_t debug_vmaddr = -1;
 uint64_t debug_fileoff = -1;
 
-bool RangeSink::ContainsVerboseVMAddr(uint64_t vmstart, uint64_t vmsize) {
+bool RangeSink::ContainsVerboseVMAddr(uint64_t vmaddr, uint64_t vmsize) {
   return options_.verbose_level() > 2 ||
-         (options_.has_debug_vmaddr() && options_.debug_vmaddr() >= vmstart &&
-          options_.debug_vmaddr() < (vmstart + vmsize));
+         (options_.has_debug_vmaddr() && options_.debug_vmaddr() >= vmaddr &&
+          options_.debug_vmaddr() < (vmaddr + vmsize));
 }
 
 bool RangeSink::ContainsVerboseFileOffset(uint64_t fileoff, uint64_t filesize) {
@@ -886,12 +886,16 @@
           options_.debug_fileoff() < (fileoff + filesize));
 }
 
-bool RangeSink::IsVerboseForVMRange(uint64_t vmstart, uint64_t vmsize) {
+bool RangeSink::IsVerboseForVMRange(uint64_t vmaddr, uint64_t vmsize) {
   if (vmsize == RangeMap::kUnknownSize) {
-    vmsize = UINT64_MAX - vmstart;
+    vmsize = UINT64_MAX - vmaddr;
   }
 
-  if (ContainsVerboseVMAddr(vmstart, vmsize)) {
+  if (vmaddr + vmsize < vmaddr) {
+    THROWF("Overflow in vm range, vmaddr=$0, vmsize=$1", vmaddr, vmsize);
+  }
+
+  if (ContainsVerboseVMAddr(vmaddr, vmsize)) {
     return true;
   }
 
@@ -899,7 +903,7 @@
     RangeMap vm_map;
     RangeMap file_map;
     bool contains = false;
-    vm_map.AddRangeWithTranslation(vmstart, vmsize, "", translator_->vm_map,
+    vm_map.AddRangeWithTranslation(vmaddr, vmsize, "", translator_->vm_map,
                                    false, &file_map);
     file_map.ForEachRange(
         [this, &contains](uint64_t fileoff, uint64_t filesize) {
@@ -918,6 +922,11 @@
     filesize = UINT64_MAX - fileoff;
   }
 
+  if (fileoff + filesize < fileoff) {
+    THROWF("Overflow in file range, fileoff=$0, filesize=$1", fileoff,
+           filesize);
+  }
+
   if (ContainsVerboseFileOffset(fileoff, filesize)) {
     return true;
   }
@@ -928,8 +937,8 @@
     bool contains = false;
     file_map.AddRangeWithTranslation(fileoff, filesize, "",
                                      translator_->file_map, false, &vm_map);
-    vm_map.ForEachRange([this, &contains](uint64_t vmstart, uint64_t vmsize) {
-      if (ContainsVerboseVMAddr(vmstart, vmsize)) {
+    vm_map.ForEachRange([this, &contains](uint64_t vmaddr, uint64_t vmsize) {
+      if (ContainsVerboseVMAddr(vmaddr, vmsize)) {
         contains = true;
       }
     });
@@ -1074,15 +1083,6 @@
     }
   }
 
-  if (vmaddr + vmsize < vmaddr) {
-    THROWF("Overflow in vm range, vmaddr=$0, vmsize=$1", vmaddr, vmsize);
-  }
-
-  if (fileoff + filesize < fileoff) {
-    THROWF("Overflow in file range, fileoff=$0, filesize=$1", fileoff,
-           filesize);
-  }
-
   for (auto& pair : outputs_) {
     const std::string label = pair.second->Munge(name);
     uint64_t common = std::min(vmsize, filesize);
diff --git a/src/bloaty.h b/src/bloaty.h
index 60a99f4..8f6f8e3 100644
--- a/src/bloaty.h
+++ b/src/bloaty.h
@@ -230,9 +230,9 @@
     return ptr >= file_data.data() && ptr < file_data.data() + file_data.size();
   }
 
-  bool ContainsVerboseVMAddr(uint64_t vmstart, uint64_t vmsize);
+  bool ContainsVerboseVMAddr(uint64_t vmaddr, uint64_t vmsize);
   bool ContainsVerboseFileOffset(uint64_t fileoff, uint64_t filesize);
-  bool IsVerboseForVMRange(uint64_t vmstart, uint64_t vmsize);
+  bool IsVerboseForVMRange(uint64_t vmaddr, uint64_t vmsize);
   bool IsVerboseForFileRange(uint64_t fileoff, uint64_t filesize);
 
   const InputFile* file_;
diff --git a/src/dwarf.cc b/src/dwarf.cc
index 13d6a82..6aae7fe 100644
--- a/src/dwarf.cc
+++ b/src/dwarf.cc
@@ -122,10 +122,6 @@
 
 // Parses the LEB128 format defined by DWARF (both signed and unsigned
 // versions).
-//
-// Bloaty doesn't actually use any LEB128's for signed values at the moment.
-// So while this attempts to implement the DWARF spec correctly with respect
-// to signed values, this isn't actually tested/exercised right now.
 
 uint64_t ReadLEB128Internal(bool is_signed, string_view* data) {
   uint64_t ret = 0;
@@ -140,7 +136,7 @@
     shift += 7;
     if ((byte & 0x80) == 0) {
       data->remove_prefix(ptr - data->data());
-      if (is_signed && (byte & 0x40)) {
+      if (is_signed && shift < 64 && (byte & 0x40)) {
         ret |= -(1ULL << shift);
       }
       return ret;
@@ -1584,9 +1580,16 @@
 
   // Sometimes a location is given as an offset into debug_loc.
   if (die.has_location_uint64()) {
-    absl::string_view loc_range = file.debug_loc.substr(die.location_uint64());
-    loc_range = GetLocationListRange(sizes, loc_range);
-    sink->AddFileRange("dwarf_locrange", name, loc_range);
+    if (die.location_uint64() < file.debug_loc.size()) {
+      absl::string_view loc_range = file.debug_loc.substr(die.location_uint64());
+      loc_range = GetLocationListRange(sizes, loc_range);
+      sink->AddFileRange("dwarf_locrange", name, loc_range);
+    } else if (verbose_level > 0) {
+      fprintf(stderr,
+              "bloaty: warning: DWARF location out of range, location=%" PRIx64
+              "\n",
+              die.location_uint64());
+    }
   }
 
   uint64_t ranges_offset = UINT64_MAX;
diff --git a/tests/testdata/fuzz_corpus/37209ceacf21ce2796c98824dc9be60b876274a2 b/tests/testdata/fuzz_corpus/37209ceacf21ce2796c98824dc9be60b876274a2
new file mode 100644
index 0000000..6f49440
--- /dev/null
+++ b/tests/testdata/fuzz_corpus/37209ceacf21ce2796c98824dc9be60b876274a2
Binary files differ
diff --git a/tests/testdata/fuzz_corpus/48c3f1ae3089b0644c6af799af2ae94ee1c5ad30 b/tests/testdata/fuzz_corpus/48c3f1ae3089b0644c6af799af2ae94ee1c5ad30
new file mode 100644
index 0000000..b699120
--- /dev/null
+++ b/tests/testdata/fuzz_corpus/48c3f1ae3089b0644c6af799af2ae94ee1c5ad30
Binary files differ
diff --git a/tests/testdata/fuzz_corpus/a64d39a8957a4f4c7012f78b41caa8e5f3f4e484 b/tests/testdata/fuzz_corpus/a64d39a8957a4f4c7012f78b41caa8e5f3f4e484
new file mode 100644
index 0000000..29684c8
--- /dev/null
+++ b/tests/testdata/fuzz_corpus/a64d39a8957a4f4c7012f78b41caa8e5f3f4e484
Binary files differ