diff --git a/cJSON.c b/cJSON.c index a839c4290f9a5c87acb7616760d68a3542ac1b2d..c81fd7d255fa8da78a1ab43d9f6053e9feefafd4 100644 --- a/cJSON.c +++ b/cJSON.c @@ -900,7 +900,7 @@ static const unsigned char *parse_value(cJSON * const item, parse_buffer * const static cJSON_bool print_value(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks); static const unsigned char *parse_array(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks); static cJSON_bool print_array(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks); -static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const ep, const internal_hooks * const hooks); +static const unsigned char *parse_object(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks); static cJSON_bool print_object(const cJSON * const item, const size_t depth, const cJSON_bool format, printbuffer * const output_buffer, const internal_hooks * const hooks); /* Utility to jump whitespace and cr/lf */ @@ -1168,7 +1168,7 @@ static const unsigned char *parse_value(cJSON * const item, parse_buffer * cons /* object */ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { - content_pointer = parse_object(item, buffer_at_offset(input_buffer), error_pointer, hooks); + content_pointer = parse_object(item, input_buffer, error_pointer, hooks); if (content_pointer == NULL) { return NULL; @@ -1423,26 +1423,35 @@ static cJSON_bool print_array(const cJSON * const item, const size_t depth, cons } /* Build an object from the text. */ -static const unsigned char *parse_object(cJSON * const item, const unsigned char *input, const unsigned char ** const error_pointer, const internal_hooks * const hooks) +static const unsigned char *parse_object(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks) { cJSON *head = NULL; /* linked list head */ cJSON *current_item = NULL; - parse_buffer input_buffer; + const unsigned char *content_pointer = NULL; - if (*input != '{') + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { - *error_pointer = input; + *error_pointer = buffer_at_offset(input_buffer); goto fail; /* not an object */ } - input = skip_whitespace(input + 1); - if (*input == '}') + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { goto success; /* empty object */ } + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + *error_pointer = buffer_at_offset(input_buffer); + goto fail; + } + /* step back to character in front of the first element */ - input--; + input_buffer->offset--; /* loop through the comma separated array elements */ do { @@ -1468,41 +1477,40 @@ static const unsigned char *parse_object(cJSON * const item, const unsigned char } /* parse the name of the child */ - input = skip_whitespace(input + 1); - input = parse_string(current_item, input, error_pointer, hooks); - input = skip_whitespace(input); - if (input == NULL) + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + content_pointer = parse_string(current_item, buffer_at_offset(input_buffer), error_pointer, hooks); + if (content_pointer == NULL) { goto fail; /* faile to parse name */ } + input_buffer->offset = (size_t)(content_pointer - input_buffer->content); + buffer_skip_whitespace(input_buffer); /* swap valuestring and string, because we parsed the name */ current_item->string = current_item->valuestring; current_item->valuestring = NULL; - if (*input != ':') + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { - *error_pointer = input; + *error_pointer = buffer_at_offset(input_buffer); goto fail; /* invalid object */ } /* parse the value */ - input = skip_whitespace(input + 1); - input_buffer.content = (const unsigned char*)input; - input_buffer.offset = 0; - input_buffer.length = strlen((const char*)input) + sizeof(""); - input = parse_value(current_item, &input_buffer, error_pointer, hooks); - input = skip_whitespace(input); - if (input == NULL) + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (parse_value(current_item, input_buffer, error_pointer, hooks) == NULL) { goto fail; /* failed to parse value */ } + buffer_skip_whitespace(input_buffer); } - while (*input == ','); + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - if (*input != '}') + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { - *error_pointer = input; + *error_pointer = buffer_at_offset(input_buffer); goto fail; /* expected end of object */ } @@ -1510,7 +1518,8 @@ success: item->type = cJSON_Object; item->child = head; - return input + 1; + input_buffer->offset++; + return buffer_at_offset(input_buffer); fail: if (head != NULL) diff --git a/tests/parse_object.c b/tests/parse_object.c index 0f8569cd829c7a318643c71e7c940553db3117df..283de822f06ae8257ce9b8e4ab61441a73efe85d 100644 --- a/tests/parse_object.c +++ b/tests/parse_object.c @@ -54,14 +54,24 @@ static void assert_is_child(cJSON *child_item, const char *name, int type) static void assert_not_object(const char *json) { - TEST_ASSERT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer, &global_hooks)); + parse_buffer parsebuffer; + parsebuffer.content = (const unsigned char*)json; + parsebuffer.length = strlen(json) + sizeof(""); + parsebuffer.offset = 0; + + TEST_ASSERT_NULL(parse_object(item, &parsebuffer, &error_pointer, &global_hooks)); assert_is_invalid(item); reset(item); } static void assert_parse_object(const char *json) { - TEST_ASSERT_NOT_NULL(parse_object(item, (const unsigned char*)json, &error_pointer, &global_hooks)); + parse_buffer parsebuffer; + parsebuffer.content = (const unsigned char*)json; + parsebuffer.length = strlen(json) + sizeof(""); + parsebuffer.offset = 0; + + TEST_ASSERT_NOT_NULL(parse_object(item, &parsebuffer, &error_pointer, &global_hooks)); assert_is_object(item); } diff --git a/tests/print_object.c b/tests/print_object.c index f7f53444729d2ae3204366ff645703a1058e050e..53fe8f2444a9031907363fdb4503fb26c6d9675a 100644 --- a/tests/print_object.c +++ b/tests/print_object.c @@ -34,6 +34,12 @@ static void assert_print_object(const char * const expected, const char * const printbuffer formatted_buffer; printbuffer unformatted_buffer; + parse_buffer parsebuffer; + + /* buffer for parsing */ + parsebuffer.content = (const unsigned char*)input; + parsebuffer.length = strlen(input) + sizeof(""); + parsebuffer.offset = 0; /* buffer for formatted printing */ formatted_buffer.buffer = printed_formatted; @@ -48,7 +54,7 @@ static void assert_print_object(const char * const expected, const char * const unformatted_buffer.noalloc = true; memset(item, 0, sizeof(item)); - TEST_ASSERT_NOT_NULL_MESSAGE(parse_object(item, (const unsigned char*)input, &error_pointer, &global_hooks), "Failed to parse object."); + TEST_ASSERT_NOT_NULL_MESSAGE(parse_object(item, &parsebuffer, &error_pointer, &global_hooks), "Failed to parse object."); TEST_ASSERT_TRUE_MESSAGE(print_object(item, 0, false, &unformatted_buffer, &global_hooks), "Failed to print unformatted string."); TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted object is not correct.");