MMDB_get_entry_data_list()now validates that the claimed array/map size is
plausible given the remaining bytes in the data section. A crafted database
could previously claim millions of array elements while only having a few
bytes of data, causing disproportionate memory allocation (memory
amplification DoS).- On Windows,
GetFileSize()was replaced withGetFileSizeEx()to correctly
handle files larger than 4GB. The previous code passedNULLfor the high
DWORD, discarding the upper 32 bits of the file size. - Fixed integer overflow in
MMDB_read_node()andfind_ipv4_start_node()
pointer arithmetic. Thenode_number * record_lengthmultiplication was
performed inuint32_t, which could overflow for very large databases. Now
cast touint64_tbefore multiplying, matching the pattern already used in
find_address_in_search_tree(). - Fixed printf format specifier mismatches in
mmdblookup's metadata dump.%i
was used for unsigned types and%lluforuint64_t, which is technically
undefined behavior. Now uses the portablePRIu32,PRIu16, andPRIu64
macros from<inttypes.h>. - Fixed an integer overflow in the search tree bounds check in
find_address_in_search_tree(). The addition ofnode_countand
data_section_sizewas performed inuint32_tarithmetic, which could wrap
on very large databases, causing valid lookups to be incorrectly rejected as
corrupt. - Fixed a NULL pointer dereference in
mmdblookupwhen displaying metadata for
a database with an out-of-rangebuild_epoch. Thegmtime()return value is
now checked before passing tostrftime(). MMDB_close()now NULLs thefile_content,data_section, and
metadata_sectionpointers and zeroesfile_size,data_section_size, and
metadata_section_sizeafter unmapping. Previously, callingMMDB_close()
twice on the same struct (or calling it after a failedMMDB_open()that
succeeded at mapping) would double-munmap the file content, which is undefined
behavior.- Fixed a stack buffer overflow in
print_indentation()when
MMDB_dump_entry_data_list()was called with a negativeindentvalue. The
negative integer was cast tosize_t, producing a massive value passed to
memset(). Negative indent values are now clamped to 0. MMDB_lookup_string()now sets*mmdb_errortoMMDB_SUCCESSwhen
getaddrinfofails (non-zero*gai_error). Previously,*mmdb_errorwas
left uninitialized in this case, which could cause callers to read an
indeterminate value.- Fixed an off-by-one in
mmdblookupon Windows whereallocaallocated one
byte too few for the program name buffer, causing_splitpathto write one
byte past the end when appending the null terminator. - Added a recursion depth limit to
skip_map_or_array(), matching the existing
MAXIMUM_DATA_STRUCTURE_DEPTH(512) limit already used by
get_entry_data_list(). A crafted MMDB file with deeply nested maps or arrays
could previously cause a stack overflow via unbounded recursion in the
MMDB_aget_value/MMDB_get_valuecode path. - Fixed an off-by-one error in
MMDB_read_node()that allowed reading one node
past the end of the search tree when called withnode_number == node_count.
This caused the function to read from the data section separator and return an
invalid record with an underflowed data offset. The check now correctly
rejectsnode_number >= node_count. - The handling of float and double types was rewritten to fix compiler errors
and to eliminate the use of volatile. - Improved endian preprocessor check if
MMDB_LITTLE_ENDIANis not set.