Update libmaxminddb and MySQL 5.7 (#2192)

* Update libmaxminddb and MySQL 5.7 (linux checkout)

* Bump libmaxminddb version

* Typo fix
This commit is contained in:
Accelerator 2024-11-02 20:01:23 +03:00 committed by GitHub
parent 34ddf6d2c8
commit 932010e63c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 195 additions and 114 deletions

View File

@ -1,3 +1,7 @@
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#include "data-pool.h" #include "data-pool.h"
#include "maxminddb.h" #include "maxminddb.h"
@ -5,8 +9,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
static bool can_multiply(size_t const, size_t const, size_t const);
// Allocate an MMDB_data_pool_s. It initially has space for size // Allocate an MMDB_data_pool_s. It initially has space for size
// MMDB_entry_data_list_s structs. // MMDB_entry_data_list_s structs.
MMDB_data_pool_s *data_pool_new(size_t const size) { MMDB_data_pool_s *data_pool_new(size_t const size) {
@ -39,7 +41,7 @@ MMDB_data_pool_s *data_pool_new(size_t const size) {
// the given max. max will typically be SIZE_MAX. // the given max. max will typically be SIZE_MAX.
// //
// We want to know if we'll wrap around. // We want to know if we'll wrap around.
static bool can_multiply(size_t const max, size_t const m, size_t const n) { bool can_multiply(size_t const max, size_t const m, size_t const n) {
if (m == 0) { if (m == 0) {
return false; return false;
} }

View File

@ -44,6 +44,7 @@ typedef struct MMDB_data_pool_s {
MMDB_entry_data_list_s *blocks[DATA_POOL_NUM_BLOCKS]; MMDB_entry_data_list_s *blocks[DATA_POOL_NUM_BLOCKS];
} MMDB_data_pool_s; } MMDB_data_pool_s;
bool can_multiply(size_t const, size_t const, size_t const);
MMDB_data_pool_s *data_pool_new(size_t const); MMDB_data_pool_s *data_pool_new(size_t const);
void data_pool_destroy(MMDB_data_pool_s *const); void data_pool_destroy(MMDB_data_pool_s *const);
MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const); MMDB_entry_data_list_s *data_pool_alloc(MMDB_data_pool_s *const);

View File

@ -42,9 +42,9 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
static void * static const void *
mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len) { mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len) {
register char *cur, *last; const char *cur, *last;
const char *cl = (const char *)l; const char *cl = (const char *)l;
const char *cs = (const char *)s; const char *cs = (const char *)s;
@ -61,9 +61,9 @@ mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len) {
return memchr(l, (int)*cs, l_len); return memchr(l, (int)*cs, l_len);
/* the last position where its possible to find "s" in "l" */ /* the last position where its possible to find "s" in "l" */
last = (char *)cl + l_len - s_len; last = cl + l_len - s_len;
for (cur = (char *)cl; cur <= last; cur++) for (cur = cl; cur <= last; cur++)
if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
return cur; return cur;

View File

@ -1,13 +1,17 @@
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif #endif
#include "data-pool.h" #include "data-pool.h"
#include "maxminddb-compat-util.h" #include "maxminddb-compat-util.h"
#include "maxminddb.h" #include "maxminddb.h"
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <inttypes.h> #include <inttypes.h>
#include <limits.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -19,6 +23,10 @@
#endif #endif
#include <windows.h> #include <windows.h>
#include <ws2ipdef.h> #include <ws2ipdef.h>
#ifndef SSIZE_MAX
#define SSIZE_MAX INTPTR_MAX
#endif
typedef ADDRESS_FAMILY sa_family_t;
#else #else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/mman.h> #include <sys/mman.h>
@ -152,7 +160,7 @@ static int populate_description_metadata(MMDB_s *mmdb,
MMDB_entry_s *metadata_start); MMDB_entry_s *metadata_start);
static int resolve_any_address(const char *ipstr, struct addrinfo **addresses); static int resolve_any_address(const char *ipstr, struct addrinfo **addresses);
static int find_address_in_search_tree(const MMDB_s *const mmdb, static int find_address_in_search_tree(const MMDB_s *const mmdb,
uint8_t *address, uint8_t const *address,
sa_family_t address_family, sa_family_t address_family,
MMDB_lookup_result_s *result); MMDB_lookup_result_s *result);
static record_info_s record_info_for_database(const MMDB_s *const mmdb); static record_info_s record_info_for_database(const MMDB_s *const mmdb);
@ -162,7 +170,7 @@ static uint32_t get_left_28_bit_record(const uint8_t *record);
static uint32_t get_right_28_bit_record(const uint8_t *record); static uint32_t get_right_28_bit_record(const uint8_t *record);
static uint32_t data_section_offset_for_record(const MMDB_s *const mmdb, static uint32_t data_section_offset_for_record(const MMDB_s *const mmdb,
uint64_t record); uint64_t record);
static int path_length(va_list va_path); static size_t path_length(va_list va_path);
static int lookup_path_in_array(const char *path_elem, static int lookup_path_in_array(const char *path_elem,
const MMDB_s *const mmdb, const MMDB_s *const mmdb,
MMDB_entry_data_s *entry_data); MMDB_entry_data_s *entry_data);
@ -201,7 +209,7 @@ dump_entry_data_list(FILE *stream,
int indent, int indent,
int *status); int *status);
static void print_indentation(FILE *stream, int i); static void print_indentation(FILE *stream, int i);
static char *bytes_to_hex(uint8_t *bytes, uint32_t size); static char *bytes_to_hex(uint8_t const *bytes, uint32_t size);
#define CHECKED_DECODE_ONE(mmdb, offset, entry_data) \ #define CHECKED_DECODE_ONE(mmdb, offset, entry_data) \
do { \ do { \
@ -284,18 +292,29 @@ int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb) {
goto cleanup; goto cleanup;
} }
uint32_t search_tree_size = if (!can_multiply(SSIZE_MAX,
mmdb->metadata.node_count * mmdb->full_record_byte_size; mmdb->metadata.node_count,
mmdb->full_record_byte_size)) {
mmdb->data_section =
mmdb->file_content + search_tree_size + MMDB_DATA_SECTION_SEPARATOR;
if (search_tree_size + MMDB_DATA_SECTION_SEPARATOR >
(uint32_t)mmdb->file_size) {
status = MMDB_INVALID_METADATA_ERROR; status = MMDB_INVALID_METADATA_ERROR;
goto cleanup; goto cleanup;
} }
mmdb->data_section_size = (uint32_t)mmdb->file_size - search_tree_size - ssize_t search_tree_size = (ssize_t)mmdb->metadata.node_count *
MMDB_DATA_SECTION_SEPARATOR; (ssize_t)mmdb->full_record_byte_size;
mmdb->data_section =
mmdb->file_content + search_tree_size + MMDB_DATA_SECTION_SEPARATOR;
if (mmdb->file_size < MMDB_DATA_SECTION_SEPARATOR ||
search_tree_size > mmdb->file_size - MMDB_DATA_SECTION_SEPARATOR) {
status = MMDB_INVALID_METADATA_ERROR;
goto cleanup;
}
ssize_t data_section_size =
mmdb->file_size - search_tree_size - MMDB_DATA_SECTION_SEPARATOR;
if (data_section_size > UINT32_MAX || data_section_size <= 0) {
status = MMDB_INVALID_METADATA_ERROR;
goto cleanup;
}
mmdb->data_section_size = (uint32_t)data_section_size;
// Although it is likely not possible to construct a database with valid // Although it is likely not possible to construct a database with valid
// valid metadata, as parsed above, and a data_section_size less than 3, // valid metadata, as parsed above, and a data_section_size less than 3,
@ -406,28 +425,39 @@ cleanup:;
#else // _WIN32 #else // _WIN32
static int map_file(MMDB_s *const mmdb) { static int map_file(MMDB_s *const mmdb) {
ssize_t size;
int status = MMDB_SUCCESS; int status = MMDB_SUCCESS;
int flags = O_RDONLY; int o_flags = O_RDONLY;
#ifdef O_CLOEXEC #ifdef O_CLOEXEC
flags |= O_CLOEXEC; o_flags |= O_CLOEXEC;
#endif #endif
int fd = open(mmdb->filename, flags); int fd = open(mmdb->filename, o_flags);
struct stat s; if (fd < 0) {
if (fd < 0 || fstat(fd, &s)) {
status = MMDB_FILE_OPEN_ERROR; status = MMDB_FILE_OPEN_ERROR;
goto cleanup; goto cleanup;
} }
size = s.st_size; #if defined(FD_CLOEXEC) && !defined(O_CLOEXEC)
if (size < 0 || size != s.st_size) { int fd_flags = fcntl(fd, F_GETFD);
if (fd_flags >= 0) {
fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC);
}
#endif
struct stat s;
if (fstat(fd, &s)) {
status = MMDB_FILE_OPEN_ERROR;
goto cleanup;
}
off_t size = s.st_size;
if (size < 0 || size > SSIZE_MAX) {
status = MMDB_OUT_OF_MEMORY_ERROR; status = MMDB_OUT_OF_MEMORY_ERROR;
goto cleanup; goto cleanup;
} }
uint8_t *file_content = uint8_t *file_content =
(uint8_t *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); (uint8_t *)mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED, fd, 0);
if (MAP_FAILED == file_content) { if (MAP_FAILED == file_content) {
if (ENOMEM == errno) { if (ENOMEM == errno) {
status = MMDB_OUT_OF_MEMORY_ERROR; status = MMDB_OUT_OF_MEMORY_ERROR;
@ -437,7 +467,7 @@ static int map_file(MMDB_s *const mmdb) {
goto cleanup; goto cleanup;
} }
mmdb->file_size = size; mmdb->file_size = (ssize_t)size;
mmdb->file_content = file_content; mmdb->file_content = file_content;
cleanup:; cleanup:;
@ -459,12 +489,16 @@ static const uint8_t *find_metadata(const uint8_t *file_content,
ssize_t max_size = file_size > METADATA_BLOCK_MAX_SIZE ssize_t max_size = file_size > METADATA_BLOCK_MAX_SIZE
? METADATA_BLOCK_MAX_SIZE ? METADATA_BLOCK_MAX_SIZE
: file_size; : file_size;
if (max_size < 0) {
return NULL;
}
uint8_t *search_area = (uint8_t *)(file_content + (file_size - max_size)); uint8_t const *search_area = (file_content + (file_size - max_size));
uint8_t *start = search_area; uint8_t const *start = search_area;
uint8_t *tmp; uint8_t const *tmp;
do { do {
tmp = mmdb_memmem(search_area, max_size, METADATA_MARKER, marker_len); tmp = mmdb_memmem(
search_area, (size_t)max_size, METADATA_MARKER, marker_len);
if (NULL != tmp) { if (NULL != tmp) {
max_size -= tmp - search_area; max_size -= tmp - search_area;
@ -671,7 +705,7 @@ value_for_key_as_string(MMDB_entry_s *start, char *key, char const **value) {
type_num_to_name(entry_data.type)); type_num_to_name(entry_data.type));
return MMDB_INVALID_METADATA_ERROR; return MMDB_INVALID_METADATA_ERROR;
} }
*value = mmdb_strndup((char *)entry_data.utf8_string, entry_data.data_size); *value = mmdb_strndup(entry_data.utf8_string, entry_data.data_size);
if (NULL == *value) { if (NULL == *value) {
return MMDB_OUT_OF_MEMORY_ERROR; return MMDB_OUT_OF_MEMORY_ERROR;
} }
@ -719,9 +753,8 @@ static int populate_languages_metadata(MMDB_s *mmdb,
return MMDB_INVALID_METADATA_ERROR; return MMDB_INVALID_METADATA_ERROR;
} }
mmdb->metadata.languages.names[i] = mmdb->metadata.languages.names[i] = mmdb_strndup(
mmdb_strndup((char *)member->entry_data.utf8_string, member->entry_data.utf8_string, member->entry_data.data_size);
member->entry_data.data_size);
if (NULL == mmdb->metadata.languages.names[i]) { if (NULL == mmdb->metadata.languages.names[i]) {
return MMDB_OUT_OF_MEMORY_ERROR; return MMDB_OUT_OF_MEMORY_ERROR;
@ -803,9 +836,8 @@ static int populate_description_metadata(MMDB_s *mmdb,
goto cleanup; goto cleanup;
} }
mmdb->metadata.description.descriptions[i]->language = mmdb->metadata.description.descriptions[i]->language = mmdb_strndup(
mmdb_strndup((char *)member->entry_data.utf8_string, member->entry_data.utf8_string, member->entry_data.data_size);
member->entry_data.data_size);
if (NULL == mmdb->metadata.description.descriptions[i]->language) { if (NULL == mmdb->metadata.description.descriptions[i]->language) {
status = MMDB_OUT_OF_MEMORY_ERROR; status = MMDB_OUT_OF_MEMORY_ERROR;
@ -819,9 +851,8 @@ static int populate_description_metadata(MMDB_s *mmdb,
goto cleanup; goto cleanup;
} }
mmdb->metadata.description.descriptions[i]->description = mmdb->metadata.description.descriptions[i]->description = mmdb_strndup(
mmdb_strndup((char *)member->entry_data.utf8_string, member->entry_data.utf8_string, member->entry_data.data_size);
member->entry_data.data_size);
if (NULL == mmdb->metadata.description.descriptions[i]->description) { if (NULL == mmdb->metadata.description.descriptions[i]->description) {
status = MMDB_OUT_OF_MEMORY_ERROR; status = MMDB_OUT_OF_MEMORY_ERROR;
@ -879,22 +910,24 @@ MMDB_lookup_result_s MMDB_lookup_sockaddr(const MMDB_s *const mmdb,
.netmask = 0, .netmask = 0,
.entry = {.mmdb = mmdb, .offset = 0}}; .entry = {.mmdb = mmdb, .offset = 0}};
uint8_t mapped_address[16], *address; uint8_t mapped_address[16];
uint8_t const *address;
if (mmdb->metadata.ip_version == 4) { if (mmdb->metadata.ip_version == 4) {
if (sockaddr->sa_family == AF_INET6) { if (sockaddr->sa_family == AF_INET6) {
*mmdb_error = MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR; *mmdb_error = MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR;
return result; return result;
} }
address = (uint8_t *)&((struct sockaddr_in *)sockaddr)->sin_addr.s_addr; address = (uint8_t const *)&((struct sockaddr_in const *)sockaddr)
->sin_addr.s_addr;
} else { } else {
if (sockaddr->sa_family == AF_INET6) { if (sockaddr->sa_family == AF_INET6) {
address = (uint8_t *)&((struct sockaddr_in6 *)sockaddr) address = (uint8_t const *)&((struct sockaddr_in6 const *)sockaddr)
->sin6_addr.s6_addr; ->sin6_addr.s6_addr;
} else { } else {
address = mapped_address; address = mapped_address;
memset(address, 0, 12); memset(mapped_address, 0, 12);
memcpy(address + 12, memcpy(mapped_address + 12,
&((struct sockaddr_in *)sockaddr)->sin_addr.s_addr, &((struct sockaddr_in const *)sockaddr)->sin_addr.s_addr,
4); 4);
} }
} }
@ -906,15 +939,15 @@ MMDB_lookup_result_s MMDB_lookup_sockaddr(const MMDB_s *const mmdb,
} }
static int find_address_in_search_tree(const MMDB_s *const mmdb, static int find_address_in_search_tree(const MMDB_s *const mmdb,
uint8_t *address, uint8_t const *address,
sa_family_t address_family, sa_family_t address_family,
MMDB_lookup_result_s *result) { MMDB_lookup_result_s *result) {
record_info_s record_info = record_info_for_database(mmdb); record_info_s record_info = record_info_for_database(mmdb);
if (0 == record_info.right_record_offset) { if (record_info.right_record_offset == 0) {
return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR; return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR;
} }
uint32_t value = 0; uint64_t value = 0;
uint16_t current_bit = 0; uint16_t current_bit = 0;
if (mmdb->metadata.ip_version == 6 && address_family == AF_INET) { if (mmdb->metadata.ip_version == 6 && address_family == AF_INET) {
value = mmdb->ipv4_start_node.node_value; value = mmdb->ipv4_start_node.node_value;
@ -928,6 +961,7 @@ static int find_address_in_search_tree(const MMDB_s *const mmdb,
uint8_t bit = uint8_t bit =
1U & (address[current_bit >> 3] >> (7 - (current_bit % 8))); 1U & (address[current_bit >> 3] >> (7 - (current_bit % 8)));
// Note that value*record_info.record_length can be larger than 2**32
record_pointer = &search_tree[value * record_info.record_length]; record_pointer = &search_tree[value * record_info.record_length];
if (record_pointer + record_info.record_length > mmdb->data_section) { if (record_pointer + record_info.record_length > mmdb->data_section) {
return MMDB_CORRUPT_SEARCH_TREE_ERROR; return MMDB_CORRUPT_SEARCH_TREE_ERROR;
@ -974,10 +1008,11 @@ static record_info_s record_info_for_database(const MMDB_s *const mmdb) {
record_info.left_record_getter = &get_uint32; record_info.left_record_getter = &get_uint32;
record_info.right_record_getter = &get_uint32; record_info.right_record_getter = &get_uint32;
record_info.right_record_offset = 4; record_info.right_record_offset = 4;
} else {
assert(false);
} }
// Callers must check that right_record_offset is non-zero in case none of
// the above conditions matched.
return record_info; return record_info;
} }
@ -990,6 +1025,9 @@ static int find_ipv4_start_node(MMDB_s *const mmdb) {
} }
record_info_s record_info = record_info_for_database(mmdb); record_info_s record_info = record_info_for_database(mmdb);
if (record_info.right_record_offset == 0) {
return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR;
}
const uint8_t *search_tree = mmdb->file_content; const uint8_t *search_tree = mmdb->file_content;
uint32_t node_value = 0; uint32_t node_value = 0;
@ -1040,7 +1078,7 @@ static uint8_t record_type(const MMDB_s *const mmdb, uint64_t record) {
static uint32_t get_left_28_bit_record(const uint8_t *record) { static uint32_t get_left_28_bit_record(const uint8_t *record) {
return record[0] * 65536 + record[1] * 256 + record[2] + return record[0] * 65536 + record[1] * 256 + record[2] +
((record[3] & 0xf0) << 20); (uint32_t)((record[3] & 0xf0) << 20);
} }
static uint32_t get_right_28_bit_record(const uint8_t *record) { static uint32_t get_right_28_bit_record(const uint8_t *record) {
@ -1052,7 +1090,7 @@ int MMDB_read_node(const MMDB_s *const mmdb,
uint32_t node_number, uint32_t node_number,
MMDB_search_node_s *const node) { MMDB_search_node_s *const node) {
record_info_s record_info = record_info_for_database(mmdb); record_info_s record_info = record_info_for_database(mmdb);
if (0 == record_info.right_record_offset) { if (record_info.right_record_offset == 0) {
return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR; return MMDB_UNKNOWN_DATABASE_FORMAT_ERROR;
} }
@ -1104,13 +1142,13 @@ int MMDB_get_value(MMDB_entry_s *const start,
int MMDB_vget_value(MMDB_entry_s *const start, int MMDB_vget_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data, MMDB_entry_data_s *const entry_data,
va_list va_path) { va_list va_path) {
int length = path_length(va_path); size_t length = path_length(va_path);
const char *path_elem; const char *path_elem;
int i = 0; int i = 0;
MAYBE_CHECK_SIZE_OVERFLOW(length, if (length == SIZE_MAX) {
SIZE_MAX / sizeof(const char *) - 1, return MMDB_INVALID_METADATA_ERROR;
MMDB_INVALID_METADATA_ERROR); }
const char **path = calloc(length + 1, sizeof(const char *)); const char **path = calloc(length + 1, sizeof(const char *));
if (NULL == path) { if (NULL == path) {
@ -1125,18 +1163,17 @@ int MMDB_vget_value(MMDB_entry_s *const start,
int status = MMDB_aget_value(start, entry_data, path); int status = MMDB_aget_value(start, entry_data, path);
free((char **)path); free(path);
return status; return status;
} }
static int path_length(va_list va_path) { static size_t path_length(va_list va_path) {
int i = 0; size_t i = 0;
const char *ignore;
va_list path_copy; va_list path_copy;
va_copy(path_copy, va_path); va_copy(path_copy, va_path);
while (NULL != (ignore = va_arg(path_copy, char *))) { while (NULL != va_arg(path_copy, char *)) {
i++; i++;
} }
@ -1209,7 +1246,7 @@ static int lookup_path_in_array(const char *path_elem,
int saved_errno = errno; int saved_errno = errno;
errno = 0; errno = 0;
int array_index = strtol(path_elem, &first_invalid, 10); long array_index = strtol(path_elem, &first_invalid, 10);
if (ERANGE == errno) { if (ERANGE == errno) {
errno = saved_errno; errno = saved_errno;
return MMDB_INVALID_LOOKUP_PATH_ERROR; return MMDB_INVALID_LOOKUP_PATH_ERROR;
@ -1224,11 +1261,11 @@ static int lookup_path_in_array(const char *path_elem,
} }
} }
if (*first_invalid || (uint32_t)array_index >= size) { if (*first_invalid || (unsigned long)array_index >= size) {
return MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR; return MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR;
} }
for (int i = 0; i < array_index; i++) { for (long i = 0; i < array_index; i++) {
/* We don't want to follow a pointer here. If the next element is a /* We don't want to follow a pointer here. If the next element is a
* pointer we simply skip it and keep going */ * pointer we simply skip it and keep going */
CHECKED_DECODE_ONE(mmdb, entry_data->offset_to_next, entry_data); CHECKED_DECODE_ONE(mmdb, entry_data->offset_to_next, entry_data);
@ -1394,7 +1431,7 @@ static int decode_one(const MMDB_s *const mmdb,
DEBUG_MSGF("Extended type: %i (%s)", type, type_num_to_name(type)); DEBUG_MSGF("Extended type: %i (%s)", type, type_num_to_name(type));
} }
entry_data->type = type; entry_data->type = (uint32_t)type;
if (type == MMDB_DATA_TYPE_POINTER) { if (type == MMDB_DATA_TYPE_POINTER) {
uint8_t psize = ((ctrl >> 3) & 3) + 1; uint8_t psize = ((ctrl >> 3) & 3) + 1;
@ -1450,6 +1487,7 @@ static int decode_one(const MMDB_s *const mmdb,
} }
size = 65821 + get_uint24(&mem[offset]); size = 65821 + get_uint24(&mem[offset]);
offset += 3; offset += 3;
break;
default: default:
break; break;
} }
@ -1485,28 +1523,28 @@ static int decode_one(const MMDB_s *const mmdb,
DEBUG_MSGF("uint16 of size %d", size); DEBUG_MSGF("uint16 of size %d", size);
return MMDB_INVALID_DATA_ERROR; return MMDB_INVALID_DATA_ERROR;
} }
entry_data->uint16 = (uint16_t)get_uintX(&mem[offset], size); entry_data->uint16 = (uint16_t)get_uintX(&mem[offset], (int)size);
DEBUG_MSGF("uint16 value: %u", entry_data->uint16); DEBUG_MSGF("uint16 value: %u", entry_data->uint16);
} else if (type == MMDB_DATA_TYPE_UINT32) { } else if (type == MMDB_DATA_TYPE_UINT32) {
if (size > 4) { if (size > 4) {
DEBUG_MSGF("uint32 of size %d", size); DEBUG_MSGF("uint32 of size %d", size);
return MMDB_INVALID_DATA_ERROR; return MMDB_INVALID_DATA_ERROR;
} }
entry_data->uint32 = (uint32_t)get_uintX(&mem[offset], size); entry_data->uint32 = (uint32_t)get_uintX(&mem[offset], (int)size);
DEBUG_MSGF("uint32 value: %u", entry_data->uint32); DEBUG_MSGF("uint32 value: %u", entry_data->uint32);
} else if (type == MMDB_DATA_TYPE_INT32) { } else if (type == MMDB_DATA_TYPE_INT32) {
if (size > 4) { if (size > 4) {
DEBUG_MSGF("int32 of size %d", size); DEBUG_MSGF("int32 of size %d", size);
return MMDB_INVALID_DATA_ERROR; return MMDB_INVALID_DATA_ERROR;
} }
entry_data->int32 = get_sintX(&mem[offset], size); entry_data->int32 = get_sintX(&mem[offset], (int)size);
DEBUG_MSGF("int32 value: %i", entry_data->int32); DEBUG_MSGF("int32 value: %i", entry_data->int32);
} else if (type == MMDB_DATA_TYPE_UINT64) { } else if (type == MMDB_DATA_TYPE_UINT64) {
if (size > 8) { if (size > 8) {
DEBUG_MSGF("uint64 of size %d", size); DEBUG_MSGF("uint64 of size %d", size);
return MMDB_INVALID_DATA_ERROR; return MMDB_INVALID_DATA_ERROR;
} }
entry_data->uint64 = get_uintX(&mem[offset], size); entry_data->uint64 = get_uintX(&mem[offset], (int)size);
DEBUG_MSGF("uint64 value: %" PRIu64, entry_data->uint64); DEBUG_MSGF("uint64 value: %" PRIu64, entry_data->uint64);
} else if (type == MMDB_DATA_TYPE_UINT128) { } else if (type == MMDB_DATA_TYPE_UINT128) {
if (size > 16) { if (size > 16) {
@ -1519,7 +1557,7 @@ static int decode_one(const MMDB_s *const mmdb,
memcpy(entry_data->uint128 + 16 - size, &mem[offset], size); memcpy(entry_data->uint128 + 16 - size, &mem[offset], size);
} }
#else #else
entry_data->uint128 = get_uint128(&mem[offset], size); entry_data->uint128 = get_uint128(&mem[offset], (int)size);
#endif #endif
} else if (type == MMDB_DATA_TYPE_FLOAT) { } else if (type == MMDB_DATA_TYPE_FLOAT) {
if (size != 4) { if (size != 4) {
@ -1538,7 +1576,7 @@ static int decode_one(const MMDB_s *const mmdb,
entry_data->double_value = get_ieee754_double(&mem[offset]); entry_data->double_value = get_ieee754_double(&mem[offset]);
DEBUG_MSGF("double value: %f", entry_data->double_value); DEBUG_MSGF("double value: %f", entry_data->double_value);
} else if (type == MMDB_DATA_TYPE_UTF8_STRING) { } else if (type == MMDB_DATA_TYPE_UTF8_STRING) {
entry_data->utf8_string = size == 0 ? "" : (char *)&mem[offset]; entry_data->utf8_string = size == 0 ? "" : (char const *)&mem[offset];
entry_data->data_size = size; entry_data->data_size = size;
#ifdef MMDB_DEBUG #ifdef MMDB_DEBUG
char *string = char *string =
@ -1566,13 +1604,15 @@ get_ptr_from(uint8_t ctrl, uint8_t const *const ptr, int ptr_size) {
uint32_t new_offset; uint32_t new_offset;
switch (ptr_size) { switch (ptr_size) {
case 1: case 1:
new_offset = ((ctrl & 7) << 8) + ptr[0]; new_offset = (uint32_t)((ctrl & 7) << 8) + ptr[0];
break; break;
case 2: case 2:
new_offset = 2048 + ((ctrl & 7) << 16) + (ptr[0] << 8) + ptr[1]; new_offset = 2048 + (uint32_t)((ctrl & 7) << 16) +
(uint32_t)(ptr[0] << 8) + ptr[1];
break; break;
case 3: case 3:
new_offset = 2048 + 524288 + ((ctrl & 7) << 24) + get_uint24(ptr); new_offset =
2048 + 524288 + (uint32_t)((ctrl & 7) << 24) + get_uint24(ptr);
break; break;
case 4: case 4:
default: default:
@ -1720,7 +1760,7 @@ static int get_entry_data_list(const MMDB_s *const mmdb,
static float get_ieee754_float(const uint8_t *restrict p) { static float get_ieee754_float(const uint8_t *restrict p) {
volatile float f; volatile float f;
uint8_t *q = (void *)&f; volatile uint8_t *q = (volatile void *)&f;
/* Windows builds don't use autoconf but we can assume they're all /* Windows builds don't use autoconf but we can assume they're all
* little-endian. */ * little-endian. */
#if MMDB_LITTLE_ENDIAN || _WIN32 #if MMDB_LITTLE_ENDIAN || _WIN32
@ -1736,7 +1776,7 @@ static float get_ieee754_float(const uint8_t *restrict p) {
static double get_ieee754_double(const uint8_t *restrict p) { static double get_ieee754_double(const uint8_t *restrict p) {
volatile double d; volatile double d;
uint8_t *q = (void *)&d; volatile uint8_t *q = (volatile void *)&d;
#if MMDB_LITTLE_ENDIAN || _WIN32 #if MMDB_LITTLE_ENDIAN || _WIN32
q[7] = p[0]; q[7] = p[0];
q[6] = p[1]; q[6] = p[1];
@ -1791,7 +1831,16 @@ static void free_mmdb_struct(MMDB_s *const mmdb) {
} }
if (NULL != mmdb->filename) { if (NULL != mmdb->filename) {
#if defined(__clang__)
// This is a const char * that we need to free, which isn't valid. However it
// would mean changing the public API to fix this.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
FREE_AND_SET_NULL(mmdb->filename); FREE_AND_SET_NULL(mmdb->filename);
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} }
if (NULL != mmdb->file_content) { if (NULL != mmdb->file_content) {
#ifdef _WIN32 #ifdef _WIN32
@ -1800,12 +1849,30 @@ static void free_mmdb_struct(MMDB_s *const mmdb) {
* to cleanup then. */ * to cleanup then. */
WSACleanup(); WSACleanup();
#else #else
munmap((void *)mmdb->file_content, mmdb->file_size); #if defined(__clang__)
// This is a const char * that we need to free, which isn't valid. However it
// would mean changing the public API to fix this.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
munmap((void *)mmdb->file_content, (size_t)mmdb->file_size);
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif #endif
} }
if (NULL != mmdb->metadata.database_type) { if (NULL != mmdb->metadata.database_type) {
#if defined(__clang__)
// This is a const char * that we need to free, which isn't valid. However it
// would mean changing the public API to fix this.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
FREE_AND_SET_NULL(mmdb->metadata.database_type); FREE_AND_SET_NULL(mmdb->metadata.database_type);
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} }
free_languages_metadata(mmdb); free_languages_metadata(mmdb);
@ -1818,7 +1885,16 @@ static void free_languages_metadata(MMDB_s *mmdb) {
} }
for (size_t i = 0; i < mmdb->metadata.languages.count; i++) { for (size_t i = 0; i < mmdb->metadata.languages.count; i++) {
#if defined(__clang__)
// This is a const char * that we need to free, which isn't valid. However it
// would mean changing the public API to fix this.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
FREE_AND_SET_NULL(mmdb->metadata.languages.names[i]); FREE_AND_SET_NULL(mmdb->metadata.languages.names[i]);
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} }
FREE_AND_SET_NULL(mmdb->metadata.languages.names); FREE_AND_SET_NULL(mmdb->metadata.languages.names);
} }
@ -1831,14 +1907,32 @@ static void free_descriptions_metadata(MMDB_s *mmdb) {
for (size_t i = 0; i < mmdb->metadata.description.count; i++) { for (size_t i = 0; i < mmdb->metadata.description.count; i++) {
if (NULL != mmdb->metadata.description.descriptions[i]) { if (NULL != mmdb->metadata.description.descriptions[i]) {
if (NULL != mmdb->metadata.description.descriptions[i]->language) { if (NULL != mmdb->metadata.description.descriptions[i]->language) {
#if defined(__clang__)
// This is a const char * that we need to free, which isn't valid. However it
// would mean changing the public API to fix this.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
FREE_AND_SET_NULL( FREE_AND_SET_NULL(
mmdb->metadata.description.descriptions[i]->language); mmdb->metadata.description.descriptions[i]->language);
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} }
if (NULL != if (NULL !=
mmdb->metadata.description.descriptions[i]->description) { mmdb->metadata.description.descriptions[i]->description) {
#if defined(__clang__)
// This is a const char * that we need to free, which isn't valid. However it
// would mean changing the public API to fix this.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcast-qual"
#endif
FREE_AND_SET_NULL( FREE_AND_SET_NULL(
mmdb->metadata.description.descriptions[i]->description); mmdb->metadata.description.descriptions[i]->description);
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} }
FREE_AND_SET_NULL(mmdb->metadata.description.descriptions[i]); FREE_AND_SET_NULL(mmdb->metadata.description.descriptions[i]);
} }
@ -1879,9 +1973,9 @@ dump_entry_data_list(FILE *stream,
*status = MMDB_INVALID_DATA_ERROR; *status = MMDB_INVALID_DATA_ERROR;
return NULL; return NULL;
} }
char *key = mmdb_strndup( char *key =
(char *)entry_data_list->entry_data.utf8_string, mmdb_strndup(entry_data_list->entry_data.utf8_string,
entry_data_list->entry_data.data_size); entry_data_list->entry_data.data_size);
if (NULL == key) { if (NULL == key) {
*status = MMDB_OUT_OF_MEMORY_ERROR; *status = MMDB_OUT_OF_MEMORY_ERROR;
return NULL; return NULL;
@ -1926,9 +2020,8 @@ dump_entry_data_list(FILE *stream,
fprintf(stream, "]\n"); fprintf(stream, "]\n");
} break; } break;
case MMDB_DATA_TYPE_UTF8_STRING: { case MMDB_DATA_TYPE_UTF8_STRING: {
char *string = char *string = mmdb_strndup(entry_data_list->entry_data.utf8_string,
mmdb_strndup((char *)entry_data_list->entry_data.utf8_string, entry_data_list->entry_data.data_size);
entry_data_list->entry_data.data_size);
if (NULL == string) { if (NULL == string) {
*status = MMDB_OUT_OF_MEMORY_ERROR; *status = MMDB_OUT_OF_MEMORY_ERROR;
return NULL; return NULL;
@ -1940,7 +2033,7 @@ dump_entry_data_list(FILE *stream,
} break; } break;
case MMDB_DATA_TYPE_BYTES: { case MMDB_DATA_TYPE_BYTES: {
char *hex_string = char *hex_string =
bytes_to_hex((uint8_t *)entry_data_list->entry_data.bytes, bytes_to_hex(entry_data_list->entry_data.bytes,
entry_data_list->entry_data.data_size); entry_data_list->entry_data.data_size);
if (NULL == hex_string) { if (NULL == hex_string) {
@ -2032,12 +2125,12 @@ dump_entry_data_list(FILE *stream,
static void print_indentation(FILE *stream, int i) { static void print_indentation(FILE *stream, int i) {
char buffer[1024]; char buffer[1024];
int size = i >= 1024 ? 1023 : i; int size = i >= 1024 ? 1023 : i;
memset(buffer, 32, size); memset(buffer, 32, (size_t)size);
buffer[size] = '\0'; buffer[size] = '\0';
fputs(buffer, stream); fputs(buffer, stream);
} }
static char *bytes_to_hex(uint8_t *bytes, uint32_t size) { static char *bytes_to_hex(uint8_t const *bytes, uint32_t size) {
char *hex_string; char *hex_string;
MAYBE_CHECK_SIZE_OVERFLOW(size, SIZE_MAX / 2 - 1, NULL); MAYBE_CHECK_SIZE_OVERFLOW(size, SIZE_MAX / 2 - 1, NULL);

View File

@ -5,18 +5,6 @@ extern "C" {
#ifndef MAXMINDDB_H #ifndef MAXMINDDB_H
#define MAXMINDDB_H #define MAXMINDDB_H
/* Request POSIX.1-2008. However, we want to remain compatible with
* POSIX.1-2001 (since we have been historically and see no reason to drop
* compatibility). By requesting POSIX.1-2008, we can conditionally use
* features provided by that standard if the implementation provides it. We can
* check for what the implementation provides by checking the _POSIX_VERSION
* macro after including unistd.h. If a feature is in POSIX.1-2008 but not
* POSIX.1-2001, check that macro before using the feature (or check for the
* feature directly if possible). */
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#include "maxminddb_config.h" #include "maxminddb_config.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
@ -28,9 +16,6 @@ extern "C" {
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
/* libmaxminddb package version from configure */ /* libmaxminddb package version from configure */
#define PACKAGE_VERSION "1.5.2"
typedef ADDRESS_FAMILY sa_family_t;
#if defined(_MSC_VER) #if defined(_MSC_VER)
/* MSVC doesn't define signed size_t, copy it from configure */ /* MSVC doesn't define signed size_t, copy it from configure */

View File

@ -11,6 +11,6 @@
#define MMDB_UINT128_USING_MODE 0 #define MMDB_UINT128_USING_MODE 0
#define MMDB_UINT128_IS_BYTE_ARRAY 1 #define MMDB_UINT128_IS_BYTE_ARRAY 1
#define PACKAGE_VERSION "1.5.2" #define PACKAGE_VERSION "1.10.0"
#endif /* MAXMINDDB_CONFIG_H */ #endif /* MAXMINDDB_CONFIG_H */

View File

@ -16,7 +16,7 @@ if SM.mysql_root:
if binary.compiler.target.platform == 'linux' or binary.compiler.target.platform == 'mac': if binary.compiler.target.platform == 'linux' or binary.compiler.target.platform == 'mac':
binary.compiler.postlink += [ binary.compiler.postlink += [
os.path.join(SM.mysql_root[arch], 'lib', 'libmysqlclient_r.a'), os.path.join(SM.mysql_root[arch], 'lib', 'libmysqlclient.a'),
'-lz', '-lz',
'-lpthread', '-lpthread',
'-lm', '-lm',

View File

@ -64,13 +64,13 @@ if [ $ismac -eq 1 ]; then
mysqlver=mysql-5.5.28-osx10.5-x86 mysqlver=mysql-5.5.28-osx10.5-x86
mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext
elif [ $iswin -eq 1 ]; then elif [ $iswin -eq 1 ]; then
mysqlver=mysql-5.5.54-win32 mysqlver=mysql-5.5.62-win32
mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext
# The folder in the zip archive does not contain the substring "-noinstall", so strip it # The folder in the zip archive does not contain the substring "-noinstall", so strip it
mysqlver=${mysqlver/-noinstall} mysqlver=${mysqlver/-noinstall}
else else
mysqlver=mysql-5.6.15-linux-glibc2.5-i686 mysqlver=mysql-5.7.44-linux-glibc2.12-i686
mysqlurl=https://cdn.mysql.com/archives/mysql-5.6/$mysqlver.$archive_ext mysqlurl=https://cdn.mysql.com/archives/mysql-5.7/$mysqlver.$archive_ext
fi fi
if [ $download_mysql -eq 1 ]; then if [ $download_mysql -eq 1 ]; then
getmysql getmysql
@ -82,11 +82,11 @@ if [ $ismac -eq 1 ]; then
mysqlver=mysql-5.5.28-osx10.5-x86_64 mysqlver=mysql-5.5.28-osx10.5-x86_64
mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext
elif [ $iswin -eq 1 ]; then elif [ $iswin -eq 1 ]; then
mysqlver=mysql-5.5.54-winx64 mysqlver=mysql-5.5.62-winx64
mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext mysqlurl=https://cdn.mysql.com/archives/mysql-5.5/$mysqlver.$archive_ext
else else
mysqlver=mysql-5.6.15-linux-glibc2.5-x86_64 mysqlver=mysql-5.7.44-linux-glibc2.12-x86_64
mysqlurl=https://cdn.mysql.com/archives/mysql-5.6/$mysqlver.$archive_ext mysqlurl=https://cdn.mysql.com/archives/mysql-5.7/$mysqlver.$archive_ext
fi fi
if [ $download_mysql -eq 1 ]; then if [ $download_mysql -eq 1 ]; then
getmysql getmysql