diff --git a/Makefile b/Makefile index 4e727b73..b858861d 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) INSTALL ?= cp -a -CC = gcc -std=c89 +CC = gcc -std=c11 # validate gcc version for use fstack-protector-strong MIN_GCC_VERSION = "4.9" @@ -66,7 +66,7 @@ UTILS_STATIC = $(UTILS_LIBNAME).$(STATIC) SHARED_CMD = $(CC) -shared -o -.PHONY: all shared static tests clean install +.PHONY: all shared static tests mytests clean install all: shared static tests @@ -79,6 +79,9 @@ tests: $(CJSON_TEST) test: tests ./$(CJSON_TEST) +mytests: cJSON.c mytest.c cJSON.h + gcc -std=c11 -ggdb3 $(R_CFLAGS) cJSON.c mytest.c -o $@ $(LDLIBS) -I. + .c.o: $(CC) -c $(R_CFLAGS) $< diff --git a/cJSON.c b/cJSON.c index 23270c48..39ceaab9 100644 --- a/cJSON.c +++ b/cJSON.c @@ -44,7 +44,7 @@ #include #include #include - +#include #ifdef ENABLE_LOCALES #include #endif @@ -102,6 +102,17 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) 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) { if (!cJSON_IsNumber(item)) @@ -301,6 +312,7 @@ typedef struct static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) { double number = 0; + uint64_t number64; unsigned char *after_end = NULL; unsigned char number_c_string[64]; unsigned char decimal_point = get_decimal_point(); @@ -367,7 +379,12 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu { item->valueint = (int)number; } - + number64 = strtoull((const char*)number_c_string, (char**)&after_end, 10); + if(number_c_string == after_end) + { + return false; + } + item->valueint64 = number64; item->type = cJSON_Number; input_buffer->offset += (size_t)(after_end - number_c_string); @@ -769,7 +786,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_end = buffer_at_offset(input_buffer) + 1; unsigned char *output_pointer = NULL; + unsigned char *output_pointer_before = NULL; unsigned char *output = NULL; + size_t string_length = 0; /* not a string */ if (buffer_at_offset(input_buffer)[0] != '\"') @@ -808,8 +827,8 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu { goto fail; /* allocation failure */ } + string_length = allocation_length - sizeof("") + skipped_bytes; } - output_pointer = output; /* loop through the string literal */ while (input_pointer < input_end) @@ -826,7 +845,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu { goto fail; } - + string_length++; switch (input_pointer[1]) { case 'b': @@ -852,18 +871,21 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu /* UTF-16 literal */ case 'u': + output_pointer_before = output_pointer; sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); if (sequence_length == 0) { /* failed to convert UTF16-literal to UTF-8 */ goto fail; } + string_length += (unsigned int)(output_pointer - output_pointer_before - 1); break; default: goto fail; } input_pointer += sequence_length; + string_length -= sequence_length; } } @@ -872,6 +894,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu item->type = cJSON_String; item->valuestring = (char*)output; + item->valuestring_len = string_length; input_buffer->offset = (size_t) (input_end - input_buffer->content); input_buffer->offset++; diff --git a/cJSON.h b/cJSON.h index 0c6c8e07..b2dec41d 100644 --- a/cJSON.h +++ b/cJSON.h @@ -84,7 +84,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ #define CJSON_VERSION_PATCH 13 #include - +#include /* cJSON Types: */ #define cJSON_Invalid (0) #define cJSON_False (1 << 0) @@ -117,9 +117,10 @@ typedef struct cJSON int valueint; /* The item's number, if type==cJSON_Number */ double valuedouble; - + uint64_t valueint64; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ char *string; + size_t valuestring_len; } cJSON; typedef struct cJSON_Hooks @@ -177,7 +178,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); /* Check item type and return its value */ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item); +CJSON_PUBLIC(size_t) cJSON_GetStringValueLength(cJSON *item); CJSON_PUBLIC(double) cJSON_GetNumberValue(cJSON *item); +CJSON_PUBLIC(long int) cJSON_Get64NumberValue(cJSON *item); /* These functions check the type of an item */ CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); diff --git a/cJSON_Utils.c b/cJSON_Utils.c index c750f7fc..ecc6b862 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -836,7 +836,7 @@ static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_ { if (opcode == REMOVE) { - static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL}; + static const cJSON invalid = { NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, 0, NULL, 0}; overwrite_item(object, invalid); diff --git a/mytest.c b/mytest.c new file mode 100644 index 00000000..34ebcfa0 --- /dev/null +++ b/mytest.c @@ -0,0 +1,35 @@ +#include "cJSON.h" +#include +#include + +char JSON_STR[] = "{ \"val\": \"\\u0000\\u0001\", \"vval\":true, \"test_plain\":\"\\r\\n\", \"plain_text\": \"i'm a text\", \"test_int64\": 18446744073709551610}"; +int main(void) { + printf("%s\n", JSON_STR); + cJSON *json = cJSON_Parse(JSON_STR); + if(json == NULL) { + printf("could not parse\n"); + return 1; + } + cJSON *json1 = cJSON_GetObjectItem(json, "val"); + if(json1 == NULL) { + printf("could not get val\n"); + } + printf("val is : *%s*\n", cJSON_GetStringValue(json1)); + cJSON *json2 = cJSON_GetObjectItem(json, "test_plain"); + if(json2 == NULL) { + printf("could not get val\n"); + } + printf("val is : *%s*\n", cJSON_GetStringValue(json2)); + cJSON *json3 = cJSON_GetObjectItem(json, "plain_text"); + if(json3 == NULL) { + printf("could not get val\n"); + } + cJSON *json4 = cJSON_GetObjectItem(json, "test_int64"); + printf("got int 64 val: %016lx\n", json4->valueint64); + double asDouble = cJSON_GetNumberValue(json4); + int asInt = json4->valueint; + printf("got val: %e %lx %u\n",asDouble, *((uint64_t*)&asDouble), asInt); + printf("val is : *%s*\nlen is : %lu as opposed to: %lu\n", cJSON_GetStringValue(json3), json3->valuestring_len, strlen(json3->valuestring)); + cJSON_Delete(json); + return 0; +}