Skip to content

Commit

Permalink
Add protection against integer overflow
Browse files Browse the repository at this point in the history
  • Loading branch information
James McLaughlin committed Feb 12, 2012
1 parent c5c8d6d commit 778f9e0
Showing 1 changed file with 28 additions and 8 deletions.
36 changes: 28 additions & 8 deletions json.c
Expand Up @@ -59,18 +59,24 @@ 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;

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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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");
Expand Down

0 comments on commit 778f9e0

Please sign in to comment.