@@ -518,7 +518,7 @@ static const uint8_t *find_metadata(const uint8_t *file_content,
518518 }
519519 } while (NULL != tmp );
520520
521- if (search_area == start ) {
521+ if (search_area == start || max_size <= 0 ) {
522522 return NULL ;
523523 }
524524
@@ -926,23 +926,33 @@ MMDB_lookup_result_s MMDB_lookup_sockaddr(const MMDB_s *const mmdb,
926926
927927 uint8_t mapped_address [16 ];
928928 uint8_t const * address ;
929+ // Reject families other than AF_INET/AF_INET6 before casting to
930+ // sockaddr_in/sockaddr_in6, which would otherwise read past the
931+ // truncated struct sockaddr the caller passed in.
929932 if (mmdb -> metadata .ip_version == 4 ) {
930933 if (sockaddr -> sa_family == AF_INET6 ) {
931934 * mmdb_error = MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR ;
932935 return result ;
933936 }
937+ if (sockaddr -> sa_family != AF_INET ) {
938+ * mmdb_error = MMDB_INVALID_NETWORK_ADDRESS_ERROR ;
939+ return result ;
940+ }
934941 address = (uint8_t const * )& ((struct sockaddr_in const * )sockaddr )
935942 -> sin_addr .s_addr ;
936943 } else {
937944 if (sockaddr -> sa_family == AF_INET6 ) {
938945 address = (uint8_t const * )& ((struct sockaddr_in6 const * )sockaddr )
939946 -> sin6_addr .s6_addr ;
940- } else {
947+ } else if ( sockaddr -> sa_family == AF_INET ) {
941948 address = mapped_address ;
942949 memset (mapped_address , 0 , 12 );
943950 memcpy (mapped_address + 12 ,
944951 & ((struct sockaddr_in const * )sockaddr )-> sin_addr .s_addr ,
945952 4 );
953+ } else {
954+ * mmdb_error = MMDB_INVALID_NETWORK_ADDRESS_ERROR ;
955+ return result ;
946956 }
947957 }
948958
@@ -990,12 +1000,12 @@ static int find_address_in_search_tree(const MMDB_s *const mmdb,
9901000
9911001 result -> netmask = current_bit ;
9921002
993- if ( value >= ( uint64_t ) node_count + mmdb -> data_section_size ) {
994- // The pointer points off the end of the database.
1003+ uint8_t type = record_type ( mmdb , value );
1004+ if ( type == MMDB_RECORD_TYPE_INVALID ) {
9951005 return MMDB_CORRUPT_SEARCH_TREE_ERROR ;
9961006 }
9971007
998- if (value == node_count ) {
1008+ if (type == MMDB_RECORD_TYPE_EMPTY ) {
9991009 // record is empty
10001010 result -> found_entry = false;
10011011 return MMDB_SUCCESS ;
@@ -1083,7 +1093,14 @@ static uint8_t record_type(const MMDB_s *const mmdb, uint64_t record) {
10831093 return MMDB_RECORD_TYPE_EMPTY ;
10841094 }
10851095
1086- if (record - node_count < mmdb -> data_section_size ) {
1096+ uint64_t data_offset = record - node_count ;
1097+ if (data_offset < MMDB_DATA_SECTION_SEPARATOR ) {
1098+ DEBUG_MSG ("record points into the data section separator" );
1099+ return MMDB_RECORD_TYPE_INVALID ;
1100+ }
1101+
1102+ data_offset -= MMDB_DATA_SECTION_SEPARATOR ;
1103+ if (data_offset < mmdb -> data_section_size ) {
10871104 return MMDB_RECORD_TYPE_DATA ;
10881105 }
10891106
@@ -1126,6 +1143,11 @@ int MMDB_read_node(const MMDB_s *const mmdb,
11261143 node -> left_record_type = record_type (mmdb , node -> left_record );
11271144 node -> right_record_type = record_type (mmdb , node -> right_record );
11281145
1146+ if (node -> left_record_type == MMDB_RECORD_TYPE_INVALID ||
1147+ node -> right_record_type == MMDB_RECORD_TYPE_INVALID ) {
1148+ return MMDB_CORRUPT_SEARCH_TREE_ERROR ;
1149+ }
1150+
11291151 // Note that offset will be invalid if the record type is not
11301152 // MMDB_RECORD_TYPE_DATA, but that's ok. Any use of the record entry
11311153 // for other data types is a programming error.
@@ -1421,6 +1443,13 @@ static int decode_one(const MMDB_s *const mmdb,
14211443 MMDB_entry_data_s * entry_data ) {
14221444 const uint8_t * mem = mmdb -> data_section ;
14231445
1446+ if (mmdb -> data_section_size == 0 ) {
1447+ // decode_one is also called with a fake mmdb whose data_section
1448+ // points at the metadata; either way an empty section is invalid.
1449+ DEBUG_MSG ("decode_one called with an empty section" );
1450+ return MMDB_INVALID_DATA_ERROR ;
1451+ }
1452+
14241453 // We subtract rather than add as it possible that offset + 1
14251454 // could overflow for a corrupt database while an underflow
14261455 // from data_section_size - 1 should not be possible.
@@ -2254,6 +2283,9 @@ const char *MMDB_strerror(int error_code) {
22542283 case MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR :
22552284 return "You attempted to look up an IPv6 address in an IPv4-only "
22562285 "database" ;
2286+ case MMDB_INVALID_NETWORK_ADDRESS_ERROR :
2287+ return "The sockaddr family is unsupported; only AF_INET and "
2288+ "AF_INET6 are accepted" ;
22572289 default :
22582290 return "Unknown error code" ;
22592291 }
0 commit comments