From e96a791d9a0886a24ce08afe13207e8e105542e3 Mon Sep 17 00:00:00 2001 From: mmentovai Date: Thu, 31 May 2007 15:54:06 +0000 Subject: Check allocation and array sizes in minidump.cc (#12). r=bryner http://groups.google.com/group/google-breakpad-dev/browse_thread/thread/7258b34d26ffc890 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@182 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/processor/minidump.cc | 98 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 17 deletions(-) (limited to 'src/processor/minidump.cc') diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index e1828a6b..ed0ba365 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -686,6 +686,9 @@ void MinidumpContext::Print() { // +u_int32_t MinidumpMemoryRegion::max_bytes_ = 1024 * 1024; // 1MB + + MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump) : MinidumpObject(minidump), descriptor_(NULL), @@ -724,7 +727,13 @@ const u_int8_t* MinidumpMemoryRegion::GetMemory() { return NULL; } - // TODO(mmentovai): verify rational size! + if (descriptor_->memory.data_size > max_bytes_) { + BPLOG(ERROR) << "MinidumpMemoryRegion size " << + descriptor_->memory.data_size << " exceeds maximum " << + max_bytes_; + return NULL; + } + scoped_ptr< vector > memory( new vector(descriptor_->memory.data_size)); @@ -1014,6 +1023,9 @@ void MinidumpThread::Print() { // +u_int32_t MinidumpThreadList::max_threads_ = 256; + + MinidumpThreadList::MinidumpThreadList(Minidump* minidump) : MinidumpStream(minidump), id_to_thread_map_(), @@ -1064,8 +1076,13 @@ bool MinidumpThreadList::Read(u_int32_t expected_size) { return false; } - if (thread_count) { - // TODO(mmentovai): verify rational size! + if (thread_count > max_threads_) { + BPLOG(ERROR) << "MinidumpThreadList count " << thread_count << + " exceeds maximum " << max_threads_; + return false; + } + + if (thread_count != 0) { scoped_ptr threads( new MinidumpThreads(thread_count, MinidumpThread(minidump_))); @@ -1157,6 +1174,10 @@ void MinidumpThreadList::Print() { // +u_int32_t MinidumpModule::max_cv_bytes_ = 1024; +u_int32_t MinidumpModule::max_misc_bytes_ = 1024; + + MinidumpModule::MinidumpModule(Minidump* minidump) : MinidumpObject(minidump), module_valid_(false), @@ -1526,7 +1547,12 @@ const u_int8_t* MinidumpModule::GetCVRecord(u_int32_t* size) { return NULL; } - // TODO(mmentovai): verify rational size! + if (module_.cv_record.data_size > max_cv_bytes_) { + BPLOG(ERROR) << "MinidumpModule CodeView record size " << + module_.cv_record.data_size << " exceeds maximum " << + max_cv_bytes_; + return NULL; + } // Allocating something that will be accessed as MDCVInfoPDB70 or // MDCVInfoPDB20 but is allocated as u_int8_t[] can cause alignment @@ -1649,7 +1675,12 @@ const MDImageDebugMisc* MinidumpModule::GetMiscRecord(u_int32_t* size) { return NULL; } - // TODO(mmentovai): verify rational size! + if (module_.misc_record.data_size > max_misc_bytes_) { + BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " << + module_.misc_record.data_size << " exceeds maximum " << + max_misc_bytes_; + return NULL; + } // Allocating something that will be accessed as MDImageDebugMisc but // is allocated as u_int8_t[] can cause alignment problems. x86 and @@ -1847,6 +1878,9 @@ void MinidumpModule::Print() { // +u_int32_t MinidumpModuleList::max_modules_ = 1024; + + MinidumpModuleList::MinidumpModuleList(Minidump* minidump) : MinidumpStream(minidump), range_map_(new RangeMap()), @@ -1898,8 +1932,13 @@ bool MinidumpModuleList::Read(u_int32_t expected_size) { return false; } - if (module_count) { - // TODO(mmentovai): verify rational size! + if (module_count > max_modules_) { + BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ << + " exceeds maximum " << max_modules_; + return false; + } + + if (module_count != 0) { scoped_ptr modules( new MinidumpModules(module_count, MinidumpModule(minidump_))); @@ -2065,6 +2104,9 @@ void MinidumpModuleList::Print() { // +u_int32_t MinidumpMemoryList::max_regions_ = 256; + + MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) : MinidumpStream(minidump), range_map_(new RangeMap()), @@ -2120,8 +2162,13 @@ bool MinidumpMemoryList::Read(u_int32_t expected_size) { return false; } - if (region_count) { - // TODO(mmentovai): verify rational size! + if (region_count > max_regions_) { + BPLOG(ERROR) << "MinidumpMemoryList count " << region_count << + " exceeds maximum " << max_regions_; + return false; + } + + if (region_count != 0) { scoped_ptr descriptors( new MemoryDescriptors(region_count)); @@ -2821,6 +2868,10 @@ void MinidumpBreakpadInfo::Print() { // +u_int32_t Minidump::max_streams_ = 128; +unsigned int Minidump::max_string_length_ = 1024; + + Minidump::Minidump(const string& path) : header_(), directory_(NULL), @@ -2934,8 +2985,13 @@ bool Minidump::Read() { return false; } - if (header_.stream_count) { - // TODO(mmentovai): verify rational size! + if (header_.stream_count > max_streams_) { + BPLOG(ERROR) << "Minidump stream count " << header_.stream_count << + " exceeds maximum " << max_streams_; + return false; + } + + if (header_.stream_count != 0) { scoped_ptr directory( new MinidumpDirectoryEntries(header_.stream_count)); @@ -3146,31 +3202,39 @@ string* Minidump::ReadString(off_t offset) { return NULL; } if (!SeekSet(offset)) { - BPLOG(ERROR) << "ReadString could not seek to string"; + BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset; return NULL; } u_int32_t bytes; if (!ReadBytes(&bytes, sizeof(bytes))) { - BPLOG(ERROR) << "ReadString could not read string size"; + BPLOG(ERROR) << "ReadString could not read string size at offset " << + offset; return NULL; } if (swap_) Swap(&bytes); if (bytes % 2 != 0) { - BPLOG(ERROR) << "ReadString found odd-sized string of " << bytes << - " bytes at offset " << offset; + BPLOG(ERROR) << "ReadString found odd-sized " << bytes << + "-byte string at offset " << offset; return NULL; } unsigned int utf16_words = bytes / 2; - // TODO(mmentovai): verify rational size! + if (utf16_words > max_string_length_) { + BPLOG(ERROR) << "ReadString string length " << utf16_words << + " exceeds maximum " << max_string_length_ << + " at offset " << offset; + return NULL; + } + vector string_utf16(utf16_words); if (utf16_words) { if (!ReadBytes(&string_utf16[0], bytes)) { - BPLOG(ERROR) << "ReadString could not read string"; + BPLOG(ERROR) << "ReadString could not read " << bytes << + "-byte string at offset " << offset; return NULL; } } -- cgit v1.2.1