Strengthen range checks in minidump.cc (#173). r=bryner

http://groups.google.com/group/google-breakpad-dev/browse_thread/thread/ad373296bfe5e08b


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@173 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
mmentovai 2007-05-21 21:02:04 +00:00
parent 65571f17ed
commit fabb8714a7

View file

@ -49,6 +49,7 @@ typedef SSIZE_T ssize_t;
#endif // _WIN32 #endif // _WIN32
#include <cassert> #include <cassert>
#include <limits>
#include <map> #include <map>
#include <vector> #include <vector>
@ -64,6 +65,7 @@ typedef SSIZE_T ssize_t;
namespace google_breakpad { namespace google_breakpad {
using std::numeric_limits;
using std::vector; using std::vector;
@ -699,9 +701,9 @@ MinidumpMemoryRegion::~MinidumpMemoryRegion() {
void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) { void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) {
descriptor_ = descriptor; descriptor_ = descriptor;
valid_ = descriptor && valid_ = descriptor &&
(descriptor_->start_of_memory_range + descriptor_->memory.data_size <=
descriptor_->memory.data_size) > numeric_limits<uint64_t>::max() -
descriptor_->start_of_memory_range; descriptor_->start_of_memory_range;
} }
@ -779,6 +781,7 @@ bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(u_int64_t address,
} }
if (address < descriptor_->start_of_memory_range || if (address < descriptor_->start_of_memory_range ||
sizeof(T) > numeric_limits<u_int64_t>::max() - address ||
address + sizeof(T) > descriptor_->start_of_memory_range + address + sizeof(T) > descriptor_->start_of_memory_range +
descriptor_->memory.data_size) { descriptor_->memory.data_size) {
BPLOG(ERROR) << "MinidumpMemoryRegion request out of range: " << BPLOG(ERROR) << "MinidumpMemoryRegion request out of range: " <<
@ -894,16 +897,13 @@ bool MinidumpThread::Read() {
Swap(&thread_.thread_context); Swap(&thread_.thread_context);
} }
// Check for base + size overflow or undersize. A separate size==0 // Check for base + size overflow or undersize.
// check is needed in case base == 0.
u_int64_t high_address = thread_.stack.start_of_memory_range +
thread_.stack.memory.data_size - 1;
if (thread_.stack.memory.data_size == 0 || if (thread_.stack.memory.data_size == 0 ||
high_address < thread_.stack.start_of_memory_range) { thread_.stack.memory.data_size > numeric_limits<u_int64_t>::max() -
thread_.stack.start_of_memory_range) {
BPLOG(ERROR) << "MinidumpThread has a memory region problem, " << BPLOG(ERROR) << "MinidumpThread has a memory region problem, " <<
HexString(thread_.stack.start_of_memory_range) << "+" << HexString(thread_.stack.start_of_memory_range) << "+" <<
HexString(thread_.stack.memory.data_size) << ", " << HexString(thread_.stack.memory.data_size);
HexString(high_address);
return false; return false;
} }
@ -1050,6 +1050,12 @@ bool MinidumpThreadList::Read(u_int32_t expected_size) {
if (minidump_->swap()) if (minidump_->swap())
Swap(&thread_count); Swap(&thread_count);
if (thread_count > numeric_limits<u_int32_t>::max() / sizeof(MDRawThread)) {
BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count <<
" would cause multiplication overflow";
return false;
}
if (expected_size != sizeof(thread_count) + if (expected_size != sizeof(thread_count) +
thread_count * sizeof(MDRawThread)) { thread_count * sizeof(MDRawThread)) {
BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size << BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size <<
@ -1212,14 +1218,13 @@ bool MinidumpModule::Read() {
// are their proper widths). // are their proper widths).
} }
// Check for base + size overflow or undersize. A separate size==0 // Check for base + size overflow or undersize.
// check is needed in case base == 0. if (module_.size_of_image == 0 ||
u_int64_t high_address = module_.base_of_image + module_.size_of_image - 1; module_.size_of_image >
if (module_.size_of_image == 0 || high_address < module_.base_of_image) { numeric_limits<u_int64_t>::max() - module_.base_of_image) {
BPLOG(ERROR) << "MinidumpModule has a module problem, " << BPLOG(ERROR) << "MinidumpModule has a module problem, " <<
HexString(module_.base_of_image) << "+" << HexString(module_.base_of_image) << "+" <<
HexString(module_.size_of_image) << ", " << HexString(module_.size_of_image);
HexString(high_address);
return false; return false;
} }
@ -1878,6 +1883,12 @@ bool MinidumpModuleList::Read(u_int32_t expected_size) {
if (minidump_->swap()) if (minidump_->swap())
Swap(&module_count); Swap(&module_count);
if (module_count > numeric_limits<u_int32_t>::max() / MD_MODULE_SIZE) {
BPLOG(ERROR) << "MinidumpModuleList module count " << module_count <<
" would cause multiplication overflow";
return false;
}
if (expected_size != sizeof(module_count) + if (expected_size != sizeof(module_count) +
module_count * MD_MODULE_SIZE) { module_count * MD_MODULE_SIZE) {
BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size << BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size <<
@ -2094,6 +2105,13 @@ bool MinidumpMemoryList::Read(u_int32_t expected_size) {
if (minidump_->swap()) if (minidump_->swap())
Swap(&region_count); Swap(&region_count);
if (region_count >
numeric_limits<u_int32_t>::max() / sizeof(MDMemoryDescriptor)) {
BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count <<
" would cause multiplication overflow";
return false;
}
if (expected_size != sizeof(region_count) + if (expected_size != sizeof(region_count) +
region_count * sizeof(MDMemoryDescriptor)) { region_count * sizeof(MDMemoryDescriptor)) {
BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size << BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size <<
@ -2128,15 +2146,13 @@ bool MinidumpMemoryList::Read(u_int32_t expected_size) {
u_int64_t base_address = descriptor->start_of_memory_range; u_int64_t base_address = descriptor->start_of_memory_range;
u_int32_t region_size = descriptor->memory.data_size; u_int32_t region_size = descriptor->memory.data_size;
// Check for base + size overflow or undersize. A separate size==0 // Check for base + size overflow or undersize.
// check is needed in case base == 0. if (region_size == 0 ||
u_int64_t high_address = base_address + region_size - 1; region_size > numeric_limits<u_int64_t>::max() - base_address) {
if (region_size == 0 || high_address < base_address) {
BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " << BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " <<
" region " << region_index << "/" << region_count << " region " << region_index << "/" << region_count <<
", " << HexString(base_address) << "+" << ", " << HexString(base_address) << "+" <<
HexString(region_size) << ", " << HexString(region_size);
HexString(high_address);
return false; return false;
} }