From: Even Rouault Date: Mon, 11 Jan 2016 11:15:54 +0000 (+0100) Subject: Fix various potential null ptr deref and int32 overflows X-Git-Tag: json-c-0.13-20171207~170^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F219%2Fhead;p=thirdparty%2Fjson-c.git Fix various potential null ptr deref and int32 overflows This fix errors that can happen when ingesting very large JSON files when hitting the maximum heap size of the process. --- diff --git a/arraylist.c b/arraylist.c index 8efe006e..65ddeaf2 100644 --- a/arraylist.c +++ b/arraylist.c @@ -11,6 +11,8 @@ #include "config.h" +#include + #ifdef STDC_HEADERS # include # include @@ -62,10 +64,17 @@ static int array_list_expand_internal(struct array_list *arr, int max) int new_size; if(max < arr->size) return 0; - new_size = arr->size << 1; - if (new_size < max) + /* Avoid undefined behaviour on int32 overflow */ + if( arr->size >= INT_MAX / 2 ) new_size = max; - if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1; + else + { + new_size = arr->size << 1; + if (new_size < max) + new_size = max; + } + if((size_t)new_size > (~((size_t)0)) / sizeof(void*)) return -1; + if(!(t = realloc(arr->array, ((size_t)new_size)*sizeof(void*)))) return -1; arr->array = (void**)t; (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*)); arr->size = new_size; @@ -75,6 +84,7 @@ static int array_list_expand_internal(struct array_list *arr, int max) int array_list_put_idx(struct array_list *arr, int idx, void *data) { + if( idx < 0 || idx > INT_MAX - 1 ) return -1; if(array_list_expand_internal(arr, idx+1)) return -1; if(arr->array[idx]) arr->free_fn(arr->array[idx]); arr->array[idx] = data; diff --git a/json_object.c b/json_object.c index e611103e..821ae107 100644 --- a/json_object.c +++ b/json_object.c @@ -934,6 +934,11 @@ struct json_object* json_object_new_array(void) jso->_delete = &json_object_array_delete; jso->_to_json_string = &json_object_array_to_json_string; jso->o.c_array = array_list_new(&json_object_array_entry_free); + if(jso->o.c_array == NULL) + { + free(jso); + return NULL; + } return jso; } diff --git a/json_tokener.c b/json_tokener.c index 752a7b39..8b65ee02 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -286,11 +286,15 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, state = json_tokener_state_eatws; saved_state = json_tokener_state_object_field_start; current = json_object_new_object(); + if(current == NULL) + goto out; break; case '[': state = json_tokener_state_eatws; saved_state = json_tokener_state_array; current = json_object_new_array(); + if(current == NULL) + goto out; break; case 'I': case 'i': @@ -376,6 +380,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, if (tok->st_pos == json_inf_str_len) { current = json_object_new_double(is_negative ? -INFINITY : INFINITY); + if(current == NULL) + goto out; saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; goto redo_char; @@ -413,6 +419,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, if (tok->st_pos == json_nan_str_len) { current = json_object_new_double(NAN); + if (current == NULL) + goto out; saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; goto redo_char; @@ -486,6 +494,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, if(c == tok->quote_char) { printbuf_memappend_fast(tok->pb, case_start, str-case_start); current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos); + if(current == NULL) + goto out; saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; break; @@ -646,6 +656,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, ) { if(tok->st_pos == json_true_str_len) { current = json_object_new_boolean(1); + if(current == NULL) + goto out; saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; goto redo_char; @@ -655,6 +667,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) { if(tok->st_pos == json_false_str_len) { current = json_object_new_boolean(0); + if(current == NULL) + goto out; saved_state = json_tokener_state_finish; state = json_tokener_state_eatws; goto redo_char; @@ -737,10 +751,14 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, goto out; } current = json_object_new_int64(num64); + if(current == NULL) + goto out; } else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0) { current = json_object_new_double_s(numd, tok->pb->buf); + if(current == NULL) + goto out; } else { tok->err = json_tokener_error_parse_number; goto out; @@ -775,7 +793,8 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, break; case json_tokener_state_array_add: - json_object_array_add(current, obj); + if( json_object_array_add(current, obj) != 0 ) + goto out; saved_state = json_tokener_state_array_sep; state = json_tokener_state_eatws; goto redo_char;