Skip to content
This repository
Browse code

Add protection against integer overflow

  • Loading branch information...
commit 778f9e0c743c7d66a1c5d59d0e0942ff2595e882 1 parent c5c8d6d
James McLaughlin authored February 12, 2012

Showing 1 changed file with 28 additions and 8 deletions. Show diff stats Hide diff stats

  1. 36  json.c
36  json.c
@@ -59,9 +59,12 @@ static unsigned char hex_value (json_char c)
59 59
 typedef struct
60 60
 {
61 61
    json_settings settings;
  62
+   int first_pass;
62 63
 
63 64
    unsigned long used_memory;
64  
-   int first_pass;
  65
+
  66
+   unsigned int uint_max;
  67
+   unsigned long ulong_max;
65 68
 
66 69
 } json_state;
67 70
 
@@ -69,8 +72,11 @@ static void * json_alloc (json_state * state, unsigned long size, int zero)
69 72
 {
70 73
    void * mem;
71 74
 
72  
-   if (state->settings.max_memory &&
73  
-         (state->used_memory += size) > state->settings.max_memory)
  75
+   if ((state->ulong_max - state->used_memory) < size)
  76
+      return 0;
  77
+
  78
+   if (state->settings.max_memory
  79
+         && (state->used_memory += size) > state->settings.max_memory)
74 80
    {
75 81
       return 0;
76 82
    }
@@ -183,19 +189,23 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
183 189
    json_state state;
184 190
    int flags;
185 191
 
  192
+   memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
  193
+   memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
  194
+
  195
+   state.uint_max -= 8; /* limit of how much can be added before next check */
  196
+   state.ulong_max -= 8;
  197
+
186 198
    error[0] = '\0';
187 199
 
188 200
    memset (&state, 0, sizeof (json_state));
189 201
    memcpy (&state.settings, settings, sizeof (json_settings));
190 202
 
191  
-   state.first_pass = 1;
192  
-
193  
-   for (; state.first_pass >= 0; -- state.first_pass)
  203
+   for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
194 204
    {
195 205
       json_uchar uchar;
196 206
       unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
197 207
       json_char * string;
198  
-      int string_length;
  208
+      unsigned int string_length;
199 209
 
200 210
       top = root = 0;
201 211
       flags = flag_seek_value;
@@ -214,6 +224,9 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
214 224
                goto e_failed;
215 225
             }
216 226
 
  227
+            if (string_length > state.uint_max)
  228
+               goto e_overflow;
  229
+
217 230
             if (flags & flag_escaped)
218 231
             {
219 232
                flags &= ~ flag_escaped;
@@ -600,7 +613,9 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
600 613
                };
601 614
             }
602 615
 
603  
-            ++ top->parent->u.array.length;
  616
+            if ( (++ top->parent->u.array.length) > state.uint_max)
  617
+               goto e_overflow;
  618
+
604 619
             top = top->parent;
605 620
 
606 621
             continue;
@@ -622,6 +637,11 @@ json_value * json_parse_ex (json_settings * settings, const json_char * json, ch
622 637
    strcpy (error, "Memory allocation failure");
623 638
    goto e_failed;
624 639
 
  640
+e_overflow:
  641
+
  642
+   sprintf (error, "%d:%d: Too long (caught overflow)", cur_line, e_off);
  643
+   goto e_failed;
  644
+
625 645
 e_failed:
626 646
 
627 647
    strcpy (error_buf, *error ? error : "Unknown error");

0 notes on commit 778f9e0

Please sign in to comment.
Something went wrong with that request. Please try again.