From 778f9e0c743c7d66a1c5d59d0e0942ff2595e882 Mon Sep 17 00:00:00 2001 From: James McLaughlin Date: Sun, 12 Feb 2012 23:28:55 +0000 Subject: [PATCH] Add protection against integer overflow --- json.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/json.c b/json.c index c9e28c51..38ea2b5f 100644 --- a/json.c +++ b/json.c @@ -59,9 +59,12 @@ static unsigned char hex_value (json_char c) typedef struct { json_settings settings; + int first_pass; unsigned long used_memory; - int first_pass; + + unsigned int uint_max; + unsigned long ulong_max; } json_state; @@ -69,8 +72,11 @@ static void * json_alloc (json_state * state, unsigned long size, int zero) { void * mem; - if (state->settings.max_memory && - (state->used_memory += size) > state->settings.max_memory) + if ((state->ulong_max - state->used_memory) < size) + return 0; + + if (state->settings.max_memory + && (state->used_memory += size) > state->settings.max_memory) { return 0; } @@ -183,19 +189,23 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch json_state state; int flags; + memset (&state.uint_max, 0xFF, sizeof (state.uint_max)); + memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max)); + + state.uint_max -= 8; /* limit of how much can be added before next check */ + state.ulong_max -= 8; + error[0] = '\0'; memset (&state, 0, sizeof (json_state)); memcpy (&state.settings, settings, sizeof (json_settings)); - state.first_pass = 1; - - for (; state.first_pass >= 0; -- state.first_pass) + for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass) { json_uchar uchar; unsigned char uc_b1, uc_b2, uc_b3, uc_b4; json_char * string; - int string_length; + unsigned int string_length; top = root = 0; flags = flag_seek_value; @@ -214,6 +224,9 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch goto e_failed; } + if (string_length > state.uint_max) + goto e_overflow; + if (flags & flag_escaped) { flags &= ~ flag_escaped; @@ -600,7 +613,9 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch }; } - ++ top->parent->u.array.length; + if ( (++ top->parent->u.array.length) > state.uint_max) + goto e_overflow; + top = top->parent; continue; @@ -622,6 +637,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch strcpy (error, "Memory allocation failure"); goto e_failed; +e_overflow: + + sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off); + goto e_failed; + e_failed: strcpy (error_buf, *error ? error : "Unknown error");