wallet, bdbro: Enforce overflow data lengths

The total length of the data in an overflow record is being given to us.
We should validate that the length is reasonable (fits in the total size
of the file), and to stop reading additional data if the amount of data
read exceeds the stated legnth. This prevents infinite looping behavior.
This commit is contained in:
Ava Chow
2026-03-30 13:00:05 -07:00
parent f6e6fad0d9
commit dc3a2b9c3b

View File

@@ -626,6 +626,7 @@ void BerkeleyRODatabase::Open()
if (inner_meta.last_page > outer_meta.last_page) {
throw std::runtime_error("Subdatabase last page is greater than database last page");
}
uint64_t max_data_size = static_cast<uint64_t>(outer_meta.last_page) * page_size;
// Make sure encryption is disabled
if (inner_meta.encrypt_algo != 0) {
@@ -673,6 +674,9 @@ void BerkeleyRODatabase::Open()
} else if (const OverflowRecord* orec = std::get_if<OverflowRecord>(&rec)) {
if (orec->m_header.deleted) continue;
uint32_t next_page = orec->page_number;
if (orec->item_len > max_data_size) {
throw std::runtime_error("Overflow record has an impossible length");
}
while (next_page != 0) {
SeekToPage(db_file, next_page, page_size);
PageHeader opage_header(next_page, inner_meta.other_endian);
@@ -683,6 +687,9 @@ void BerkeleyRODatabase::Open()
OverflowPage opage(opage_header);
db_file >> opage;
data.insert(data.end(), opage.data.begin(), opage.data.end());
if (data.size() > orec->item_len) {
throw std::runtime_error("Overflow record data is larger than stated size");
}
next_page = opage_header.next_page;
}
}