10 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

1
README
View File

@@ -24,6 +24,7 @@ Github repo for json-c:
Then
$ ./configure
$ touch aclocal.m4 Makefile.in # hack around automake dependencies
$ make
$ make install

View File

@@ -552,6 +552,7 @@ int64_t json_object_get_int64(struct json_object *jso)
return jso->o.c_boolean;
case json_type_string:
if (json_parse_int64(jso->o.c_string.str, &cint) == 0) return cint;
// fallthrough
default:
return 0;
}

View File

@@ -305,6 +305,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
// fallthrough
case '"':
state = json_tokener_state_string;
printbuf_reset(tok->pb);
@@ -684,6 +685,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
(c == 'i' || c == 'I'))
{
state = json_tokener_state_inf;
tok->st_pos = 0;
goto redo_char;
}
}

View File

@@ -10,6 +10,7 @@
*
*/
#include <assert.h>
#include <stdio.h>
#include <string.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) */
switch(length) /* all the case statements fall through */
{
case 12: c+=((uint32_t)k[11])<<24;
case 11: c+=((uint32_t)k[10])<<16;
case 10: c+=((uint32_t)k[9])<<8;
case 9 : c+=k[8];
case 8 : b+=((uint32_t)k[7])<<24;
case 7 : b+=((uint32_t)k[6])<<16;
case 6 : b+=((uint32_t)k[5])<<8;
case 5 : b+=k[4];
case 4 : a+=((uint32_t)k[3])<<24;
case 3 : a+=((uint32_t)k[2])<<16;
case 2 : a+=((uint32_t)k[1])<<8;
case 12: c+=((uint32_t)k[11])<<24; // fallthrough
case 11: c+=((uint32_t)k[10])<<16; // fallthrough
case 10: c+=((uint32_t)k[9])<<8; // fallthrough
case 9 : c+=k[8]; // fallthrough
case 8 : b+=((uint32_t)k[7])<<24; // fallthrough
case 7 : b+=((uint32_t)k[6])<<16; // fallthrough
case 6 : b+=((uint32_t)k[5])<<8; // fallthrough
case 5 : b+=k[4]; // fallthrough
case 4 : a+=((uint32_t)k[3])<<24; // fallthrough
case 3 : a+=((uint32_t)k[2])<<16; // fallthrough
case 2 : a+=((uint32_t)k[1])<<8; // fallthrough
case 1 : a+=k[0];
break;
case 0 : return c;
@@ -431,6 +432,8 @@ struct lh_table* lh_table_new(int size, const char *name,
int i;
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));
if(!t) lh_abort("lh_table_new: calloc failed\n");
t->count = 0;
@@ -495,7 +498,14 @@ int lh_table_insert(struct lh_table *t, void *k, const void *v)
unsigned long h, n;
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);
n = h % t->size;

View File

@@ -15,6 +15,7 @@
#include "config.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -63,7 +64,16 @@ static int printbuf_extend(struct printbuf *p, int min_size)
if (p->size >= min_size)
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
MC_DEBUG("printbuf_memappend: realloc "
"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)
{
/* Prevent signed integer overflows with large buffers. */
if (size > INT_MAX - p->bpos - 1)
return -1;
if (p->size <= p->bpos + size + 1) {
if (printbuf_extend(p, p->bpos + size + 1) < 0)
return -1;
@@ -94,6 +107,9 @@ int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
if (offset == -1)
offset = pb->bpos;
/* Prevent signed integer overflows with large buffers. */
if (len > INT_MAX - offset)
return -1;
size_needed = offset + len;
if (pb->size < size_needed)
{

View File

@@ -2,9 +2,11 @@
* gcc -o utf8 utf8.c -I/home/y/include -L./.libs -ljson
*/
#include <stdio.h>
#include <string.h>
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "json_inttypes.h"
#include "json_object.h"
@@ -24,6 +26,30 @@ void print_hex( const char* s)
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()
{
const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\"";
@@ -49,5 +75,8 @@ int main()
retval = 1;
}
json_object_put(parse_result);
test_lot_of_adds();
return retval;
}

File diff suppressed because one or more lines are too long

View File

@@ -24,7 +24,7 @@ int main(int argc, char **argv)
int orig_count = 0;
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)
{
json_object_object_del(my_object, key0);
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
orig_count = 0;
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++;
if (strcmp(key, "foo2") != 0)
continue;
@@ -56,7 +56,7 @@ int main(int argc, char **argv)
int retval = 0;
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++;
if (strcmp(key2, "foo2") != 0)
continue;

View File

@@ -1,15 +1,15 @@
==== delete-in-loop test starting ====
Key at index 0 is [foo1] (kept)
Key at index 1 is [foo2] (kept)
Key at index 2 is [deleteme] (deleted)
Key at index 3 is [foo3] (kept)
Key at index 0 is [foo1] 0 (kept)
Key at index 1 is [foo2] 0 (kept)
Key at index 2 is [deleteme] 0 (deleted)
Key at index 3 is [foo3] 0 (kept)
==== replace-value first loop starting ====
Key at index 0 is [foo1]
Key at index 1 is [foo2]
Key at index 0 is [foo1] 0
Key at index 1 is [foo2] 0
replacing value for key [foo2]
Key at index 2 is [foo3]
Key at index 2 is [foo3] 0
==== second loop starting ====
Key at index 0 is [foo1]
Key at index 1 is [foo2]
Key at index 0 is [foo1] 0
Key at index 1 is [foo2] 0
pointer for key [foo2] does match
Key at index 2 is [foo3]
Key at index 2 is [foo3] 0

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));
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");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(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));
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));
json_object_put(new_obj);
}

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()={ "min": Infinity, "max": -Infinity }
new_obj.to_string()=true
new_obj.to_string()=12
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", "baz": null, "bool0": true }
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
==================================