diff --git a/json_tokener.c b/json_tokener.c index fc8fb65..c1bcaf7 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -68,6 +68,8 @@ static const int json_true_str_len = sizeof(json_true_str) - 1; static const char json_false_str[] = "false"; static const int json_false_str_len = sizeof(json_false_str) - 1; +static char *replace_null_character(struct printbuf *puf); + static const char* json_tokener_errors[] = { "success", "continue", @@ -882,7 +884,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, while(1) { if(c == tok->quote_char) { printbuf_memappend_fast(tok->pb, case_start, str-case_start); - obj_field_name = strdup(tok->pb->buf); + obj_field_name = replace_null_character(tok->pb); saved_state = json_tokener_state_object_field_end; state = json_tokener_state_eatws; break; @@ -996,3 +998,44 @@ size_t json_tokener_get_parse_end(struct json_tokener *tok) return (size_t)tok->char_offset; } +char *replace_null_character(struct printbuf *puf) +{ + if (puf->bpos - strlen(puf->buf) > 0) { + + char c; + char *str = NULL; + char *p = NULL; + int pos = 0, size = 0, str_length = 0; + int length = puf->bpos; + + while (length --) { + c = puf->buf[pos]; + + if ('\0' == c) { + size ++; + } + pos ++; + } + + pos = 0; + length = puf->bpos; + str_length = (length - size + 1) + size*6; + str = (char *)malloc(str_length * sizeof(char)); + *str = '\0'; + + while (length --) { + c = puf->buf[pos]; + + if ('\0' == c) { + strncat(str, "\\u0000", 6); + } else { + strncat(str, &c, 1); + } + pos ++; + } + p =strdup(str); + free(str); + return p; + } + return strdup(puf->buf); +} diff --git a/tests/test_parse.c b/tests/test_parse.c index c213f9b..7be7af1 100644 --- a/tests/test_parse.c +++ b/tests/test_parse.c @@ -121,6 +121,7 @@ static void test_basic_parse() single_basic_parse("{ \"foo\": [null, \"foo\"] }", 0); single_basic_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }", 0); single_basic_parse("{ \"abc\": \"blue\nred\\ngreen\" }", 0); + single_basic_parse("{ \"foo\\u0000bar\": \"foo\\u0000bar\" }", 0); // Clear serializer for these tests so we see the actual parsed value. single_basic_parse("null", 1); diff --git a/tests/test_parse.expected b/tests/test_parse.expected index af075b0..f72d38c 100644 --- a/tests/test_parse.expected +++ b/tests/test_parse.expected @@ -61,6 +61,7 @@ new_obj.to_string({ "foo": [null, "foo"] })={ "foo": [ null, "foo" ] } new_obj.to_string({ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] })={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] } new_obj.to_string({ "abc": "blue red\ngreen" })={ "abc": "blue\nred\ngreen" } +new_obj.to_string({ "foo\u0000bar": "foo\u0000bar" })={ "foo\\u0000bar": "foo\u0000bar" } new_obj.to_string(null)=null new_obj.to_string(false)=false new_obj.to_string([0e])=[ 0.0 ]