adding string length to string objects

there is an isssue with the strings in this library.
on one hand when parsing the string it's parsed from \" till \"
on the other hand when you want to actually get the data it's aviable
but if you had something like this: "data\u0000\n" it's a problem since
the \0 is before the end of the string.
To solve the zero teminrated string i added an extra value
stringvalue_len that can be retrived using a function that holds the
length of the pased string. The length takes into account the parsing of
special escaped chars.
This commit is contained in:
Eyal Gal 2020-04-30 20:58:08 +03:00
parent 7db005e028
commit 22ff396288
2 changed files with 20 additions and 2 deletions

20
cJSON.c
View File

@ -102,6 +102,17 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item)
return item->valuestring; return item->valuestring;
} }
CJSON_PUBLIC(size_t) cJSON_GetStringValueLength(cJSON *item)
{
if (!cJSON_IsString(item))
{
return 0;
}
return item->valuestring_len;
}
CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item) CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item)
{ {
if (!cJSON_IsNumber(item)) if (!cJSON_IsNumber(item))
@ -769,7 +780,9 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
unsigned char *output_pointer = NULL; unsigned char *output_pointer = NULL;
unsigned char *output_pointer_before = NULL;
unsigned char *output = NULL; unsigned char *output = NULL;
size_t string_length = 0;
/* not a string */ /* not a string */
if (buffer_at_offset(input_buffer)[0] != '\"') if (buffer_at_offset(input_buffer)[0] != '\"')
@ -808,8 +821,8 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
{ {
goto fail; /* allocation failure */ goto fail; /* allocation failure */
} }
string_length = allocation_length - sizeof("") + skipped_bytes;
} }
output_pointer = output; output_pointer = output;
/* loop through the string literal */ /* loop through the string literal */
while (input_pointer < input_end) while (input_pointer < input_end)
@ -852,26 +865,29 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
/* UTF-16 literal */ /* UTF-16 literal */
case 'u': case 'u':
output_pointer_before = output_pointer;
sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
if (sequence_length == 0) if (sequence_length == 0)
{ {
/* failed to convert UTF16-literal to UTF-8 */ /* failed to convert UTF16-literal to UTF-8 */
goto fail; goto fail;
} }
string_length += (unsigned int)(output_pointer - output_pointer_before);
break; break;
default: default:
goto fail; goto fail;
} }
input_pointer += sequence_length; input_pointer += sequence_length;
string_length -= sequence_length;
} }
} }
/* zero terminate the output */ /* zero terminate the output */
*output_pointer = '\0'; *output_pointer = '\0';
item->type = cJSON_String; item->type = cJSON_String;
item->valuestring = (char*)output; item->valuestring = (char*)output;
item->valuestring_len = string_length;
input_buffer->offset = (size_t) (input_end - input_buffer->content); input_buffer->offset = (size_t) (input_end - input_buffer->content);
input_buffer->offset++; input_buffer->offset++;

View File

@ -120,6 +120,7 @@ typedef struct cJSON
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string; char *string;
size_t valuestring_len;
} cJSON; } cJSON;
typedef struct cJSON_Hooks typedef struct cJSON_Hooks
@ -177,6 +178,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */ /* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
CJSON_PUBLIC(size_t) cJSON_GetStringValueLength(cJSON *item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item); CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item);
/* These functions check the type of an item */ /* These functions check the type of an item */