Skip to content

Commit 4d3d0a8

Browse files
authored
Merge pull request #336 from maxmind/greg/fix-search-tree-size-overflow
Fix overflow in search_tree_size
2 parents e7367c2 + 5fd2c21 commit 4d3d0a8

File tree

4 files changed

+26
-9
lines changed

4 files changed

+26
-9
lines changed

Changes.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 1.8.1
2+
3+
* On very large databases, the calculation to determine the search tree
4+
size could overflow. This was fixed and several additional guards
5+
against overflows were added. Reported by Sami Salonen. GitHub #335.
6+
17
## 1.8.0 - 2023-11-07
28

39
* `PACKAGE_VERSION` is now a private compile definition when building

src/data-pool.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#include <stddef.h>
1010
#include <stdlib.h>
1111

12-
static bool can_multiply(size_t const, size_t const, size_t const);
13-
1412
// Allocate an MMDB_data_pool_s. It initially has space for size
1513
// MMDB_entry_data_list_s structs.
1614
MMDB_data_pool_s *data_pool_new(size_t const size) {
@@ -43,7 +41,7 @@ MMDB_data_pool_s *data_pool_new(size_t const size) {
4341
// the given max. max will typically be SIZE_MAX.
4442
//
4543
// We want to know if we'll wrap around.
46-
static bool can_multiply(size_t const max, size_t const m, size_t const n) {
44+
bool can_multiply(size_t const max, size_t const m, size_t const n) {
4745
if (m == 0) {
4846
return false;
4947
}

src/data-pool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ typedef struct MMDB_data_pool_s {
4444
MMDB_entry_data_list_s *blocks[DATA_POOL_NUM_BLOCKS];
4545
} MMDB_data_pool_s;
4646

47+
bool can_multiply(size_t const, size_t const, size_t const);
4748
MMDB_data_pool_s *data_pool_new(size_t const);
4849
void data_pool_destroy(MMDB_data_pool_s *const);
4950
MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const);

src/maxminddb.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#endif
2424
#include <windows.h>
2525
#include <ws2ipdef.h>
26+
#define SSIZE_MAX INTPTR_MAX
2627
typedef ADDRESS_FAMILY sa_family_t;
2728
#else
2829
#include <arpa/inet.h>
@@ -289,18 +290,29 @@ int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb) {
289290
goto cleanup;
290291
}
291292

292-
uint32_t search_tree_size =
293-
mmdb->metadata.node_count * mmdb->full_record_byte_size;
293+
if (!can_multiply(SSIZE_MAX,
294+
mmdb->metadata.node_count,
295+
mmdb->full_record_byte_size)) {
296+
status = MMDB_INVALID_METADATA_ERROR;
297+
goto cleanup;
298+
}
299+
ssize_t search_tree_size = (ssize_t)mmdb->metadata.node_count *
300+
(ssize_t)mmdb->full_record_byte_size;
294301

295302
mmdb->data_section =
296303
mmdb->file_content + search_tree_size + MMDB_DATA_SECTION_SEPARATOR;
297-
if (search_tree_size + MMDB_DATA_SECTION_SEPARATOR >
298-
(uint32_t)mmdb->file_size) {
304+
if (mmdb->file_size < MMDB_DATA_SECTION_SEPARATOR ||
305+
search_tree_size > mmdb->file_size - MMDB_DATA_SECTION_SEPARATOR) {
306+
status = MMDB_INVALID_METADATA_ERROR;
307+
goto cleanup;
308+
}
309+
ssize_t data_section_size =
310+
mmdb->file_size - search_tree_size - MMDB_DATA_SECTION_SEPARATOR;
311+
if (data_section_size > UINT32_MAX || data_section_size <= 0) {
299312
status = MMDB_INVALID_METADATA_ERROR;
300313
goto cleanup;
301314
}
302-
mmdb->data_section_size = (uint32_t)mmdb->file_size - search_tree_size -
303-
MMDB_DATA_SECTION_SEPARATOR;
315+
mmdb->data_section_size = (uint32_t)data_section_size;
304316

305317
// Although it is likely not possible to construct a database with valid
306318
// valid metadata, as parsed above, and a data_section_size less than 3,

0 commit comments

Comments
 (0)