Compare commits

...
Author SHA1 Message Date
Eric Hawicz f2b7d0b5cb Merge pull request #611 from besser82/topic/besser82/json-c-0.12/CVE-2020-12762
json-c-0.12.x: Fix CVE-2020-12762 - json-c through 0.14 has an integer overflow and out-of-bounds write ...
2020-05-15 21:05:30 -04:00
Björn Esser 74accb17cd Fix CVE-2020-12762.
This commit is a squashed and slightly modified backport
of the following commits on the master branch:

  * 77d935b
  * d07b910
  * 519dfe1
  * a59d5ac
2020-05-15 20:56:22 +02:00
Eric Haszlakiewicz 0e1d83f980 Adjust the "-Infinity" fix on the json-c-0.12 branch to match the master branch. 2017-11-26 23:31:00 -05:00
Eric Haszlakiewicz 2fc68d46ac Note a hack that's needed when building from the json-c-0.12 git branch (vs a release tarball) to prevent the dependency handling from trying to run automake. 2017-11-26 23:28:10 -05:00
Eric Haszlakiewicz c7e3e0d2de Merge pull request #372 from jlguardi/json-c-0.12
Json-c 0.12: Fixed Infinity bug
2017-11-26 23:26:37 -05:00
Jlguardi 83c29cf1f4 Fixed #371: -Infinity correctly parsed after other Infinity 2017-11-03 09:55:39 +01:00
Jlguardi 431bd0c01e Improved testing for Infinity 2017-11-03 09:51:16 +01:00
Jlguardi 239c849575 Fixed testReplaceExisting compilation error 2017-11-03 09:32:33 +01:00
Eric Haszlakiewicz ddc97b2950 Merge pull request #365 from mbehr1/json-c-0.12
added fallthrough for gcc7
2017-10-04 18:19:40 -04:00
Matthias Behr ec8912bb91 added fallthrough for gcc7 2017-10-03 12:52:25 +02:00
11 changed files with 95 additions and 30 deletions

No files matched your search

+1
View File
@@ -24,6 +24,7 @@ Github repo for json-c:
Then Then
$ ./configure $ ./configure
$ touch aclocal.m4 Makefile.in # hack around automake dependencies
$ make $ make
$ make install $ make install
+1
View File
@@ -552,6 +552,7 @@ int64_t json_object_get_int64(struct json_object *jso)
return jso->o.c_boolean; return jso->o.c_boolean;
case json_type_string: case json_type_string:
if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint; if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint;
// fallthrough
default: default:
return 0; return 0;
} }
+2
View File
@@ -305,6 +305,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
tok->err = json_tokener_error_parse_unexpected; tok->err = json_tokener_error_parse_unexpected;
goto out; goto out;
} }
// fallthrough
case '"': case '"':
state = json_tokener_state_string; state = json_tokener_state_string;
printbuf_reset(tok->pb); printbuf_reset(tok->pb);
@@ -684,6 +685,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
(c == 'i' || c == 'I')) (c == 'i' || c == 'I'))
{ {
state = json_tokener_state_inf; state = json_tokener_state_inf;
tok->st_pos = 0;
goto redo_char; goto redo_char;
} }
} }
+22 -12
View File
@@ -10,6 +10,7 @@
* *
*/ */
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -376,17 +377,17 @@ static uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
/*-------------------------------- last block: affect all 32 bits of (c) */ /*-------------------------------- last block: affect all 32 bits of (c) */
switch(length) /* all the case statements fall through */ switch(length) /* all the case statements fall through */
{ {
case 12: c+=((uint32_t)k[11])<<24; case 12: c+=((uint32_t)k[11])<<24; // fallthrough
case 11: c+=((uint32_t)k[10])<<16; case 11: c+=((uint32_t)k[10])<<16; // fallthrough
case 10: c+=((uint32_t)k[9])<<8; case 10: c+=((uint32_t)k[9])<<8; // fallthrough
case 9 : c+=k[8]; case 9 : c+=k[8]; // fallthrough
case 8 : b+=((uint32_t)k[7])<<24; case 8 : b+=((uint32_t)k[7])<<24; // fallthrough
case 7 : b+=((uint32_t)k[6])<<16; case 7 : b+=((uint32_t)k[6])<<16; // fallthrough
case 6 : b+=((uint32_t)k[5])<<8; case 6 : b+=((uint32_t)k[5])<<8; // fallthrough
case 5 : b+=k[4]; case 5 : b+=k[4]; // fallthrough
case 4 : a+=((uint32_t)k[3])<<24; case 4 : a+=((uint32_t)k[3])<<24; // fallthrough
case 3 : a+=((uint32_t)k[2])<<16; case 3 : a+=((uint32_t)k[2])<<16; // fallthrough
case 2 : a+=((uint32_t)k[1])<<8; case 2 : a+=((uint32_t)k[1])<<8; // fallthrough
case 1 : a+=k[0]; case 1 : a+=k[0];
break; break;
case 0 : return c; case 0 : return c;
@@ -431,6 +432,8 @@ struct lh_table* lh_table_new(int size, const char *name,
int i; int i;
struct lh_table *t; struct lh_table *t;
/* Allocate space for elements to avoid divisions by zero. */
assert(size > 0);
t = (struct lh_table*)calloc(1, sizeof(struct lh_table)); t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
if(!t) lh_abort("lh_table_new: calloc failed\n"); if(!t) lh_abort("lh_table_new: calloc failed\n");
t->count = 0; t->count = 0;
@@ -495,7 +498,14 @@ int lh_table_insert(struct lh_table *t, void *k, const void *v)
unsigned long h, n; unsigned long h, n;
t->inserts++; t->inserts++;
if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2); if (t->count >= t->size * LH_LOAD_FACTOR) {
/* Avoid signed integer overflow with large tables. */
int new_size = (t->size > INT_MAX / 2) ? INT_MAX : (t->size * 2);
if (t->size == INT_MAX)
return -1;
lh_table_resize(t, new_size);
}
h = t->hash_fn(k); h = t->hash_fn(k);
n = h % t->size; n = h % t->size;
+17 -1
View File
@@ -15,6 +15,7 @@
#include "config.h" #include "config.h"
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -63,7 +64,16 @@ static int printbuf_extend(struct printbuf *p, int min_size)
if (p->size >= min_size) if (p->size >= min_size)
return 0; return 0;
new_size = json_max(p->size * 2, min_size + 8); /* Prevent signed integer overflows with large buffers. */
if (min_size > INT_MAX - 8)
return -1;
if (p->size > INT_MAX / 2)
new_size = min_size + 8;
else {
new_size = p->size * 2;
if (new_size < min_size + 8)
new_size = min_size + 8;
}
#ifdef PRINTBUF_DEBUG #ifdef PRINTBUF_DEBUG
MC_DEBUG("printbuf_memappend: realloc " MC_DEBUG("printbuf_memappend: realloc "
"bpos=%d min_size=%d old_size=%d new_size=%d\n", "bpos=%d min_size=%d old_size=%d new_size=%d\n",
@@ -78,6 +88,9 @@ static int printbuf_extend(struct printbuf *p, int min_size)
int printbuf_memappend(struct printbuf *p, const char *buf, int size) int printbuf_memappend(struct printbuf *p, const char *buf, int size)
{ {
/* Prevent signed integer overflows with large buffers. */
if (size > INT_MAX - p->bpos - 1)
return -1;
if (p->size <= p->bpos + size + 1) { if (p->size <= p->bpos + size + 1) {
if (printbuf_extend(p, p->bpos + size + 1) < 0) if (printbuf_extend(p, p->bpos + size + 1) < 0)
return -1; return -1;
@@ -94,6 +107,9 @@ int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
if (offset == -1) if (offset == -1)
offset = pb->bpos; offset = pb->bpos;
/* Prevent signed integer overflows with large buffers. */
if (len > INT_MAX - offset)
return -1;
size_needed = offset + len; size_needed = offset + len;
if (pb->size < size_needed) if (pb->size < size_needed)
{ {
+31 -2
View File
@@ -2,9 +2,11 @@
* gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson * gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson
*/ */
#include <stdio.h>
#include <string.h>
#include "config.h" #include "config.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "json_inttypes.h" #include "json_inttypes.h"
#include "json_object.h" #include "json_object.h"
@@ -24,6 +26,30 @@ void print_hex( const char* s)
printf("\n"); printf("\n");
} }
static void test_lot_of_adds(void);
static void test_lot_of_adds()
{
int ii;
char key[50];
json_object *jobj = json_object_new_object();
assert(jobj != NULL);
for (ii = 0; ii < 500; ii++)
{
snprintf(key, sizeof(key), "k%d", ii);
json_object *iobj = json_object_new_int(ii);
assert(iobj != NULL);
json_object_object_add(jobj, key, iobj);
if (json_object_object_get_ex(jobj, key, &iobj) == FALSE)
{
fprintf(stderr, "FAILED to add object #%d\n", ii);
abort();
}
}
printf("%s\n", json_object_to_json_string(jobj));
assert(json_object_object_length(jobj) == 500);
json_object_put(jobj);
}
int main() int main()
{ {
const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\""; const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\"";
@@ -49,5 +75,8 @@ int main()
retval = 1; retval = 1;
} }
json_object_put(parse_result); json_object_put(parse_result);
test_lot_of_adds();
return retval; return retval;
} }
+1
View File
@@ -1,3 +1,4 @@
input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27" input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27"
JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧 JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧
PASS PASS
{ "k0": 0, "k1": 1, "k2": 2, "k3": 3, "k4": 4, "k5": 5, "k6": 6, "k7": 7, "k8": 8, "k9": 9, "k10": 10, "k11": 11, "k12": 12, "k13": 13, "k14": 14, "k15": 15, "k16": 16, "k17": 17, "k18": 18, "k19": 19, "k20": 20, "k21": 21, "k22": 22, "k23": 23, "k24": 24, "k25": 25, "k26": 26, "k27": 27, "k28": 28, "k29": 29, "k30": 30, "k31": 31, "k32": 32, "k33": 33, "k34": 34, "k35": 35, "k36": 36, "k37": 37, "k38": 38, "k39": 39, "k40": 40, "k41": 41, "k42": 42, "k43": 43, "k44": 44, "k45": 45, "k46": 46, "k47": 47, "k48": 48, "k49": 49, "k50": 50, "k51": 51, "k52": 52, "k53": 53, "k54": 54, "k55": 55, "k56": 56, "k57": 57, "k58": 58, "k59": 59, "k60": 60, "k61": 61, "k62": 62, "k63": 63, "k64": 64, "k65": 65, "k66": 66, "k67": 67, "k68": 68, "k69": 69, "k70": 70, "k71": 71, "k72": 72, "k73": 73, "k74": 74, "k75": 75, "k76": 76, "k77": 77, "k78": 78, "k79": 79, "k80": 80, "k81": 81, "k82": 82, "k83": 83, "k84": 84, "k85": 85, "k86": 86, "k87": 87, "k88": 88, "k89": 89, "k90": 90, "k91": 91, "k92": 92, "k93": 93, "k94": 94, "k95": 95, "k96": 96, "k97": 97, "k98": 98, "k99": 99, "k100": 100, "k101": 101, "k102": 102, "k103": 103, "k104": 104, "k105": 105, "k106": 106, "k107": 107, "k108": 108, "k109": 109, "k110": 110, "k111": 111, "k112": 112, "k113": 113, "k114": 114, "k115": 115, "k116": 116, "k117": 117, "k118": 118, "k119": 119, "k120": 120, "k121": 121, "k122": 122, "k123": 123, "k124": 124, "k125": 125, "k126": 126, "k127": 127, "k128": 128, "k129": 129, "k130": 130, "k131": 131, "k132": 132, "k133": 133, "k134": 134, "k135": 135, "k136": 136, "k137": 137, "k138": 138, "k139": 139, "k140": 140, "k141": 141, "k142": 142, "k143": 143, "k144": 144, "k145": 145, "k146": 146, "k147": 147, "k148": 148, "k149": 149, "k150": 150, "k151": 151, "k152": 152, "k153": 153, "k154": 154, "k155": 155, "k156": 156, "k157": 157, "k158": 158, "k159": 159, "k160": 160, "k161": 161, "k162": 162, "k163": 163, "k164": 164, "k165": 165, "k166": 166, "k167": 167, "k168": 168, "k169": 169, "k170": 170, "k171": 171, "k172": 172, "k173": 173, "k174": 174, "k175": 175, "k176": 176, "k177": 177, "k178": 178, "k179": 179, "k180": 180, "k181": 181, "k182": 182, "k183": 183, "k184": 184, "k185": 185, "k186": 186, "k187": 187, "k188": 188, "k189": 189, "k190": 190, "k191": 191, "k192": 192, "k193": 193, "k194": 194, "k195": 195, "k196": 196, "k197": 197, "k198": 198, "k199": 199, "k200": 200, "k201": 201, "k202": 202, "k203": 203, "k204": 204, "k205": 205, "k206": 206, "k207": 207, "k208": 208, "k209": 209, "k210": 210, "k211": 211, "k212": 212, "k213": 213, "k214": 214, "k215": 215, "k216": 216, "k217": 217, "k218": 218, "k219": 219, "k220": 220, "k221": 221, "k222": 222, "k223": 223, "k224": 224, "k225": 225, "k226": 226, "k227": 227, "k228": 228, "k229": 229, "k230": 230, "k231": 231, "k232": 232, "k233": 233, "k234": 234, "k235": 235, "k236": 236, "k237": 237, "k238": 238, "k239": 239, "k240": 240, "k241": 241, "k242": 242, "k243": 243, "k244": 244, "k245": 245, "k246": 246, "k247": 247, "k248": 248, "k249": 249, "k250": 250, "k251": 251, "k252": 252, "k253": 253, "k254": 254, "k255": 255, "k256": 256, "k257": 257, "k258": 258, "k259": 259, "k260": 260, "k261": 261, "k262": 262, "k263": 263, "k264": 264, "k265": 265, "k266": 266, "k267": 267, "k268": 268, "k269": 269, "k270": 270, "k271": 271, "k272": 272, "k273": 273, "k274": 274, "k275": 275, "k276": 276, "k277": 277, "k278": 278, "k279": 279, "k280": 280, "k281": 281, "k282": 282, "k283": 283, "k284": 284, "k285": 285, "k286": 286, "k287": 287, "k288": 288, "k289": 289, "k290": 290, "k291": 291, "k292": 292, "k293": 293, "k294": 294, "k295": 295, "k296": 296, "k297": 297, "k298": 298, "k299": 299, "k300": 300, "k301": 301, "k302": 302, "k303": 303, "k304": 304, "k305": 305, "k306": 306, "k307": 307, "k308": 308, "k309": 309, "k310": 310, "k311": 311, "k312": 312, "k313": 313, "k314": 314, "k315": 315, "k316": 316, "k317": 317, "k318": 318, "k319": 319, "k320": 320, "k321": 321, "k322": 322, "k323": 323, "k324": 324, "k325": 325, "k326": 326, "k327": 327, "k328": 328, "k329": 329, "k330": 330, "k331": 331, "k332": 332, "k333": 333, "k334": 334, "k335": 335, "k336": 336, "k337": 337, "k338": 338, "k339": 339, "k340": 340, "k341": 341, "k342": 342, "k343": 343, "k344": 344, "k345": 345, "k346": 346, "k347": 347, "k348": 348, "k349": 349, "k350": 350, "k351": 351, "k352": 352, "k353": 353, "k354": 354, "k355": 355, "k356": 356, "k357": 357, "k358": 358, "k359": 359, "k360": 360, "k361": 361, "k362": 362, "k363": 363, "k364": 364, "k365": 365, "k366": 366, "k367": 367, "k368": 368, "k369": 369, "k370": 370, "k371": 371, "k372": 372, "k373": 373, "k374": 374, "k375": 375, "k376": 376, "k377": 377, "k378": 378, "k379": 379, "k380": 380, "k381": 381, "k382": 382, "k383": 383, "k384": 384, "k385": 385, "k386": 386, "k387": 387, "k388": 388, "k389": 389, "k390": 390, "k391": 391, "k392": 392, "k393": 393, "k394": 394, "k395": 395, "k396": 396, "k397": 397, "k398": 398, "k399": 399, "k400": 400, "k40Line truncated
+3 -3
View File
@@ -24,7 +24,7 @@ int main(int argc, char **argv)
int orig_count = 0; int orig_count = 0;
json_object_object_foreach(my_object, key0, val0) json_object_object_foreach(my_object, key0, val0)
{ {
printf("Key at index %d is [%s]", orig_count, key0); printf("Key at index %d is [%s] %d", orig_count, key0, (val0 == NULL));
if (strcmp(key0, "deleteme") == 0) if (strcmp(key0, "deleteme") == 0)
{ {
json_object_object_del(my_object, key0); json_object_object_del(my_object, key0);
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
orig_count = 0; orig_count = 0;
json_object_object_foreach(my_object, key, val) json_object_object_foreach(my_object, key, val)
{ {
printf("Key at index %d is [%s]\n", orig_count, key); printf("Key at index %d is [%s] %d\n", orig_count, key, (val == NULL));
orig_count++; orig_count++;
if (strcmp(key, "foo2") != 0) if (strcmp(key, "foo2") != 0)
continue; continue;
@@ -56,7 +56,7 @@ int main(int argc, char **argv)
int retval = 0; int retval = 0;
json_object_object_foreach(my_object, key2, val2) json_object_object_foreach(my_object, key2, val2)
{ {
printf("Key at index %d is [%s]\n", new_count, key2); printf("Key at index %d is [%s] %d\n", new_count, key2, (val2 == NULL));
new_count++; new_count++;
if (strcmp(key2, "foo2") != 0) if (strcmp(key2, "foo2") != 0)
continue; continue;
+10 -10
View File
@@ -1,15 +1,15 @@
==== delete-in-loop test starting ==== ==== delete-in-loop test starting ====
Key at index 0 is [foo1] (kept) Key at index 0 is [foo1] 0 (kept)
Key at index 1 is [foo2] (kept) Key at index 1 is [foo2] 0 (kept)
Key at index 2 is [deleteme] (deleted) Key at index 2 is [deleteme] 0 (deleted)
Key at index 3 is [foo3] (kept) Key at index 3 is [foo3] 0 (kept)
==== replace-value first loop starting ==== ==== replace-value first loop starting ====
Key at index 0 is [foo1] Key at index 0 is [foo1] 0
Key at index 1 is [foo2] Key at index 1 is [foo2] 0
replacing value for key [foo2] replacing value for key [foo2]
Key at index 2 is [foo3] Key at index 2 is [foo3] 0
==== second loop starting ==== ==== second loop starting ====
Key at index 0 is [foo1] Key at index 0 is [foo1] 0
Key at index 1 is [foo2] Key at index 1 is [foo2] 0
pointer for key [foo2] does match pointer for key [foo2] does match
Key at index 2 is [foo3] Key at index 2 is [foo3] 0
+5 -1
View File
@@ -79,6 +79,10 @@ static void test_basic_parse()
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj); json_object_put(new_obj);
new_obj = json_tokener_parse("{ \"min\": Infinity, \"max\": -Infinity}");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);
new_obj = json_tokener_parse("True"); new_obj = json_tokener_parse("True");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj); json_object_put(new_obj);
@@ -131,7 +135,7 @@ static void test_basic_parse()
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj); json_object_put(new_obj);
new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }"); new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ], \"inf\": Infinity, \"-inf\": -Infinity, \"nan\": NaN, \"def\" : -0.22, \"hij\": 0.31 }");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj); json_object_put(new_obj);
} }
+2 -1
View File
@@ -11,6 +11,7 @@ new_obj.to_string()=Infinity
new_obj.to_string()=Infinity new_obj.to_string()=Infinity
new_obj.to_string()=-Infinity new_obj.to_string()=-Infinity
new_obj.to_string()=-Infinity new_obj.to_string()=-Infinity
new_obj.to_string()={ "min": Infinity, "max": -Infinity }
new_obj.to_string()=true new_obj.to_string()=true
new_obj.to_string()=12 new_obj.to_string()=12
new_obj.to_string()=12.3 new_obj.to_string()=12.3
@@ -24,7 +25,7 @@ new_obj.to_string()={ }
new_obj.to_string()={ "foo": "bar" } new_obj.to_string()={ "foo": "bar" }
new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true } new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true }
new_obj.to_string()={ "foo": [ null, "foo" ] } new_obj.to_string()={ "foo": [ null, "foo" ] }
new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] } new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ], "inf": Infinity, "-inf": -Infinity, "nan": NaN, "def": -0.22, "hij": 0.31 }
================================== ==================================
json_tokener_parse_versbose() OK json_tokener_parse_versbose() OK
================================== ==================================