Skip to content

Commit 3c15105

Browse files
authored
Merge pull request #422 from maxmind/greg/eng-4322
Fix validation of empty maps/arrays at end of metadata
2 parents dd4e3d8 + b587225 commit 3c15105

File tree

7 files changed

+56
-5
lines changed

7 files changed

+56
-5
lines changed

Changes.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 1.13.3 - 2026-XX-XX
2+
3+
- Fixed validation of empty maps and arrays at the end of the metadata section.
4+
`MMDB_open` would incorrectly reject databases where a 0-element map or array
5+
was the last field in metadata. Reported in vimt/MaxMind-DB-Writer-python#16.
6+
17
## 1.13.2 - 2026-02-25
28

39
- Fixed a compilation failure on macOS 26 (Tahoe) where `sys/endian.h` defines

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR], [AC_SUBST([pkgconfigdir], [${libdir
1111
AC_CONFIG_FILES([src/libmaxminddb.pc])
1212

1313
LT_INIT
14-
AM_INIT_AUTOMAKE(foreign m4_esyscmd([case `automake --version | head -n 1` in
14+
AM_INIT_AUTOMAKE(foreign tar-ustar m4_esyscmd([case `automake --version | head -n 1` in
1515
*1.14*) echo subdir-objects;;
1616
*1.11*);;
1717
*) echo serial-tests;;

src/maxminddb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,7 +1729,7 @@ static int get_entry_data_list(const MMDB_s *const mmdb,
17291729
uint32_t array_size = entry_data_list->entry_data.data_size;
17301730
uint32_t array_offset = entry_data_list->entry_data.offset_to_next;
17311731
/* Each array element needs at least 1 byte. */
1732-
if (array_offset >= mmdb->data_section_size ||
1732+
if (array_offset > mmdb->data_section_size ||
17331733
array_size > mmdb->data_section_size - array_offset) {
17341734
DEBUG_MSG("array size exceeds remaining data section");
17351735
return MMDB_INVALID_DATA_ERROR;
@@ -1758,7 +1758,7 @@ static int get_entry_data_list(const MMDB_s *const mmdb,
17581758

17591759
offset = entry_data_list->entry_data.offset_to_next;
17601760
/* Each map entry needs at least a key and a value (1 byte each). */
1761-
if (offset >= mmdb->data_section_size ||
1761+
if (offset > mmdb->data_section_size ||
17621762
size > (mmdb->data_section_size - offset) / 2) {
17631763
DEBUG_MSG("map size exceeds remaining data section");
17641764
return MMDB_INVALID_DATA_ERROR;

t/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ if(UNIX) # or if (NOT WIN32)
3131
bad_data_size_t
3232
bad_epoch_t
3333
bad_indent_t
34+
empty_container_metadata_t
3435
max_depth_t
3536
threads_t
3637
)

t/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ check_PROGRAMS = \
1919
bad_pointers_t bad_databases_t bad_data_size_t bad_epoch_t bad_indent_t \
2020
bad_search_tree_t \
2121
basic_lookup_t data_entry_list_t \
22-
data-pool-t data_types_t double_close_t dump_t gai_error_t get_value_t \
22+
data-pool-t data_types_t double_close_t dump_t empty_container_metadata_t \
23+
gai_error_t get_value_t \
2324
get_value_pointer_bug_t \
2425
ipv4_start_cache_t ipv6_lookup_in_ipv4_t max_depth_t metadata_t \
2526
metadata_pointers_t no_map_get_value_t overflow_bounds_t read_node_t \

t/empty_container_metadata_t.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "maxminddb_test_helper.h"
2+
3+
static void test_db_opens_and_lookup_succeeds(const char *filename,
4+
const char *open_msg) {
5+
char *db_file = bad_database_path(filename);
6+
7+
MMDB_s mmdb;
8+
int status = MMDB_open(db_file, MMDB_MODE_MMAP, &mmdb);
9+
cmp_ok(status, "==", MMDB_SUCCESS, open_msg);
10+
11+
if (status != MMDB_SUCCESS) {
12+
diag("MMDB_open failed: %s", MMDB_strerror(status));
13+
free(db_file);
14+
return;
15+
}
16+
17+
int gai_error, mmdb_error;
18+
MMDB_lookup_string(&mmdb, "1.2.3.4", &gai_error, &mmdb_error);
19+
cmp_ok(gai_error, "==", 0, "getaddrinfo succeeded");
20+
cmp_ok(mmdb_error, "==", MMDB_SUCCESS, "lookup succeeded");
21+
22+
MMDB_close(&mmdb);
23+
free(db_file);
24+
}
25+
26+
void test_empty_map_last_in_metadata(void) {
27+
test_db_opens_and_lookup_succeeds(
28+
"libmaxminddb-empty-map-last-in-metadata.mmdb",
29+
"opened MMDB with empty map at end of metadata");
30+
}
31+
32+
void test_empty_array_last_in_metadata(void) {
33+
test_db_opens_and_lookup_succeeds(
34+
"libmaxminddb-empty-array-last-in-metadata.mmdb",
35+
"opened MMDB with empty array at end of metadata");
36+
}
37+
38+
int main(void) {
39+
plan(NO_PLAN);
40+
test_empty_map_last_in_metadata();
41+
test_empty_array_last_in_metadata();
42+
done_testing();
43+
}

0 commit comments

Comments
 (0)