Parcourir la source

parser: Construct error pointer from buffer offset

Max Bruckner il y a 8 ans
Parent
commit
2683589d93
8 fichiers modifiés avec 49 ajouts et 72 suppressions
  1. 39 52
      cJSON.c
  2. 2 4
      tests/parse_array.c
  3. 2 4
      tests/parse_object.c
  4. 2 4
      tests/parse_string.c
  5. 1 2
      tests/parse_value.c
  6. 1 2
      tests/print_array.c
  7. 1 2
      tests/print_object.c
  8. 1 2
      tests/print_value.c

+ 39 - 52
cJSON.c

@@ -535,7 +535,7 @@ static unsigned parse_hex4(const unsigned char * const input)
 
 /* converts a UTF-16 literal to UTF-8
  * A literal can be one or two sequences of the form \uXXXX */
-static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer, const unsigned char **error_pointer)
+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
 {
     long unsigned int codepoint = 0;
     unsigned int first_code = 0;
@@ -548,7 +548,6 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi
     if ((input_end - first_sequence) < 6)
     {
         /* input ends unexpectedly */
-        *error_pointer = first_sequence;
         goto fail;
     }
 
@@ -558,7 +557,6 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi
     /* check that the code is valid */
     if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
     {
-        *error_pointer = first_sequence;
         goto fail;
     }
 
@@ -572,14 +570,12 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi
         if ((input_end - second_sequence) < 6)
         {
             /* input ends unexpectedly */
-            *error_pointer = first_sequence;
             goto fail;
         }
 
         if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
         {
             /* missing second half of the surrogate pair */
-            *error_pointer = first_sequence;
             goto fail;
         }
 
@@ -589,7 +585,6 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi
         if ((second_code < 0xDC00) || (second_code > 0xDFFF))
         {
             /* invalid second half of the surrogate pair */
-            *error_pointer = first_sequence;
             goto fail;
         }
 
@@ -632,7 +627,6 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi
     else
     {
         /* invalid unicode codepoint */
-        *error_pointer = first_sequence;
         goto fail;
     }
 
@@ -662,7 +656,7 @@ fail:
 }
 
 /* Parse the input text into an unescaped cinput, and populate item. */
-static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
 {
     const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
     const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
@@ -672,7 +666,6 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
     /* not a string */
     if (buffer_at_offset(input_buffer)[0] != '\"')
     {
-        *error_pointer = buffer_at_offset(input_buffer);
         goto fail;
     }
 
@@ -751,7 +744,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
 
                 /* UTF-16 literal */
                 case 'u':
-                    sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer, error_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 */
@@ -760,7 +753,6 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
                     break;
 
                 default:
-                    *error_pointer = input_pointer;
                     goto fail;
             }
             input_pointer += sequence_length;
@@ -784,6 +776,11 @@ fail:
         hooks->deallocate(output);
     }
 
+    if (input_pointer != NULL)
+    {
+        input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+    }
+
     return false;
 }
 
@@ -916,11 +913,11 @@ static cJSON_bool print_string(const cJSON * const item, printbuffer * const p,
 }
 
 /* Predeclare these prototypes. */
-static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks);
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks);
 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 cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks);
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, 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 cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const ep, const internal_hooks * const hooks);
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, 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 */
@@ -951,15 +948,8 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
     /* use global error pointer if no specific one was given */
     const unsigned char **error_pointer = (return_parse_end != NULL) ? (const unsigned char**)return_parse_end : &global_ep;
     cJSON *item = NULL;
-
     *error_pointer = NULL;
 
-    item = cJSON_New_Item(&global_hooks);
-    if (item == NULL) /* memory fail */
-    {
-        goto fail;
-    }
-
     if (value == NULL)
     {
         goto fail;
@@ -969,7 +959,13 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
     buffer.length = strlen((const char*)value) + sizeof("");
     buffer.offset = 0;
 
-    if (!parse_value(item, buffer_skip_whitespace(&buffer), error_pointer, &global_hooks))
+    item = cJSON_New_Item(&global_hooks);
+    if (item == NULL) /* memory fail */
+    {
+        goto fail;
+    }
+
+    if (!parse_value(item, buffer_skip_whitespace(&buffer), &global_hooks))
     {
         /* parse failure. ep is set. */
         goto fail;
@@ -981,7 +977,6 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return
         buffer_skip_whitespace(&buffer);
         if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
         {
-            *error_pointer = buffer_at_offset(&buffer);
             goto fail;
         }
     }
@@ -998,6 +993,18 @@ fail:
         cJSON_Delete(item);
     }
 
+    if (value != NULL)
+    {
+        if (buffer.offset < buffer.length)
+        {
+            *error_pointer = buffer_at_offset(&buffer);
+        }
+        else if (buffer.length > 0)
+        {
+            *error_pointer = buffer.content + buffer.length - 1;
+        }
+    }
+
     return NULL;
 }
 
@@ -1113,7 +1120,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const i
 }
 
 /* Parser core - when encountering text, process appropriately. */
-static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
 {
     if ((input_buffer == NULL) || (input_buffer->content == NULL))
     {
@@ -1146,7 +1153,7 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf
     /* string */
     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
     {
-        return parse_string(item, input_buffer, error_pointer, hooks);
+        return parse_string(item, input_buffer, hooks);
     }
     /* number */
     if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
@@ -1156,27 +1163,14 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf
     /* array */
     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
     {
-        return parse_array(item, input_buffer, error_pointer, hooks);
+        return parse_array(item, input_buffer, hooks);
     }
     /* object */
     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
     {
-        return parse_object(item, input_buffer, error_pointer, hooks);
+        return parse_object(item, input_buffer, hooks);
     }
 
-    /* failure. */
-    if (can_access_at_index(input_buffer, 0))
-    {
-        *error_pointer = buffer_at_offset(input_buffer);
-    }
-    else if (input_buffer->length > 0)
-    {
-        *error_pointer = input_buffer->content + input_buffer->length - 1;
-    }
-    else
-    {
-        *error_pointer = input_buffer->content;
-    }
 
     return false;
 }
@@ -1260,7 +1254,7 @@ static cJSON_bool print_value(const cJSON * const item, const size_t depth, cons
 }
 
 /* Build an array from input text. */
-static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
 {
     cJSON *head = NULL; /* head of the linked list */
     cJSON *current_item = NULL;
@@ -1268,7 +1262,6 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
     if (buffer_at_offset(input_buffer)[0] != '[')
     {
         /* not an array */
-        *error_pointer = buffer_at_offset(input_buffer);
         goto fail;
     }
 
@@ -1284,7 +1277,6 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
     if (cannot_access_at_index(input_buffer, 0))
     {
         input_buffer->offset--;
-        *error_pointer = buffer_at_offset(input_buffer);
         goto fail;
     }
 
@@ -1317,7 +1309,7 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
         /* parse next value */
         input_buffer->offset++;
         buffer_skip_whitespace(input_buffer);
-        if (!parse_value(current_item, input_buffer, error_pointer, hooks))
+        if (!parse_value(current_item, input_buffer, hooks))
         {
             goto fail; /* failed to parse value */
         }
@@ -1327,7 +1319,6 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
 
     if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
     {
-        *error_pointer = buffer_at_offset(input_buffer);
         goto fail; /* expected end of array */
     }
 
@@ -1409,14 +1400,13 @@ static cJSON_bool print_array(const cJSON * const item, const size_t depth, cons
 }
 
 /* Build an object from the text. */
-static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, const unsigned char ** const error_pointer, const internal_hooks * const hooks)
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer, const internal_hooks * const hooks)
 {
     cJSON *head = NULL; /* linked list head */
     cJSON *current_item = NULL;
 
     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
     {
-        *error_pointer = buffer_at_offset(input_buffer);
         goto fail; /* not an object */
     }
 
@@ -1431,7 +1421,6 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
     if (cannot_access_at_index(input_buffer, 0))
     {
         input_buffer->offset--;
-        *error_pointer = buffer_at_offset(input_buffer);
         goto fail;
     }
 
@@ -1464,7 +1453,7 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
         /* parse the name of the child */
         input_buffer->offset++;
         buffer_skip_whitespace(input_buffer);
-        if (!parse_string(current_item, input_buffer, error_pointer, hooks))
+        if (!parse_string(current_item, input_buffer, hooks))
         {
             goto fail; /* faile to parse name */
         }
@@ -1476,14 +1465,13 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
 
         if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
         {
-            *error_pointer = buffer_at_offset(input_buffer);
             goto fail; /* invalid object */
         }
 
         /* parse the value */
         input_buffer->offset++;
         buffer_skip_whitespace(input_buffer);
-        if (!parse_value(current_item, input_buffer, error_pointer, hooks))
+        if (!parse_value(current_item, input_buffer, hooks))
         {
             goto fail; /* failed to parse value */
         }
@@ -1493,7 +1481,6 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
 
     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
     {
-        *error_pointer = buffer_at_offset(input_buffer);
         goto fail; /* expected end of object */
     }
 

+ 2 - 4
tests/parse_array.c

@@ -30,8 +30,6 @@
 
 static cJSON item[1];
 
-static const unsigned char *error_pointer = NULL;
-
 static void assert_is_array(cJSON *array_item)
 {
     TEST_ASSERT_NOT_NULL_MESSAGE(array_item, "Item is NULL.");
@@ -51,7 +49,7 @@ static void assert_not_array(const char *json)
     buffer.length = strlen(json) + sizeof("");
     buffer.offset = 0;
 
-    TEST_ASSERT_FALSE(parse_array(item, &buffer, &error_pointer, &global_hooks));
+    TEST_ASSERT_FALSE(parse_array(item, &buffer, &global_hooks));
     assert_is_invalid(item);
 }
 
@@ -62,7 +60,7 @@ static void assert_parse_array(const char *json)
     buffer.length = strlen(json) + sizeof("");
     buffer.offset = 0;
 
-    TEST_ASSERT_TRUE(parse_array(item, &buffer, &error_pointer, &global_hooks));
+    TEST_ASSERT_TRUE(parse_array(item, &buffer, &global_hooks));
     assert_is_array(item);
 }
 

+ 2 - 4
tests/parse_object.c

@@ -30,8 +30,6 @@
 
 static cJSON item[1];
 
-static const unsigned char *error_pointer = NULL;
-
 static void assert_is_object(cJSON *object_item)
 {
     TEST_ASSERT_NOT_NULL_MESSAGE(object_item, "Item is NULL.");
@@ -59,7 +57,7 @@ static void assert_not_object(const char *json)
     parsebuffer.length = strlen(json) + sizeof("");
     parsebuffer.offset = 0;
 
-    TEST_ASSERT_FALSE(parse_object(item, &parsebuffer, &error_pointer, &global_hooks));
+    TEST_ASSERT_FALSE(parse_object(item, &parsebuffer, &global_hooks));
     assert_is_invalid(item);
     reset(item);
 }
@@ -71,7 +69,7 @@ static void assert_parse_object(const char *json)
     parsebuffer.length = strlen(json) + sizeof("");
     parsebuffer.offset = 0;
 
-    TEST_ASSERT_TRUE(parse_object(item, &parsebuffer, &error_pointer, &global_hooks));
+    TEST_ASSERT_TRUE(parse_object(item, &parsebuffer, &global_hooks));
     assert_is_object(item);
 }
 

+ 2 - 4
tests/parse_string.c

@@ -30,8 +30,6 @@
 
 static cJSON item[1];
 
-static const unsigned char *error_pointer = NULL;
-
 static void assert_is_string(cJSON *string_item)
 {
     TEST_ASSERT_NOT_NULL_MESSAGE(string_item, "Item is NULL.");
@@ -52,7 +50,7 @@ static void assert_parse_string(const char *string, const char *expected)
     buffer.length = strlen(string) + sizeof("");
     buffer.offset = 0;
 
-    TEST_ASSERT_TRUE_MESSAGE(parse_string(item, &buffer, &error_pointer, &global_hooks), "Couldn't parse string.");
+    TEST_ASSERT_TRUE_MESSAGE(parse_string(item, &buffer, &global_hooks), "Couldn't parse string.");
     assert_is_string(item);
     TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, item->valuestring, "The parsed result isn't as expected.");
     global_hooks.deallocate(item->valuestring);
@@ -66,7 +64,7 @@ static void assert_not_parse_string(const char * const string)
     buffer.length = strlen(string) + sizeof("");
     buffer.offset = 0;
 
-    TEST_ASSERT_FALSE_MESSAGE(parse_string(item, &buffer, &error_pointer, &global_hooks), "Malformed string should not be accepted.");
+    TEST_ASSERT_FALSE_MESSAGE(parse_string(item, &buffer, &global_hooks), "Malformed string should not be accepted.");
     assert_is_invalid(item);
 }
 

+ 1 - 2
tests/parse_value.c

@@ -29,7 +29,6 @@
 #include "common.h"
 
 static cJSON item[1];
-const unsigned char *error_pointer = NULL;
 
 static void assert_is_value(cJSON *value_item, int type)
 {
@@ -48,7 +47,7 @@ static void assert_parse_value(const char *string, int type)
     buffer.content = (const unsigned char*) string;
     buffer.length = strlen(string) + sizeof("");
     buffer.offset = 0;
-    TEST_ASSERT_TRUE(parse_value(item, &buffer, &error_pointer, &global_hooks));
+    TEST_ASSERT_TRUE(parse_value(item, &buffer, &global_hooks));
     assert_is_value(item, type);
 }
 

+ 1 - 2
tests/print_array.c

@@ -29,7 +29,6 @@ static void assert_print_array(const char * const expected, const char * const i
     unsigned char printed_unformatted[1024];
     unsigned char printed_formatted[1024];
 
-    const unsigned char *error_pointer;
     cJSON item[1];
 
     printbuffer formatted_buffer;
@@ -53,7 +52,7 @@ static void assert_print_array(const char * const expected, const char * const i
     unformatted_buffer.noalloc = true;
 
     memset(item, 0, sizeof(item));
-    TEST_ASSERT_TRUE_MESSAGE(parse_array(item, &parsebuffer, &error_pointer, &global_hooks), "Failed to parse array.");
+    TEST_ASSERT_TRUE_MESSAGE(parse_array(item, &parsebuffer, &global_hooks), "Failed to parse array.");
 
     TEST_ASSERT_TRUE_MESSAGE(print_array(item, 0, false, &unformatted_buffer, &global_hooks), "Failed to print unformatted string.");
     TEST_ASSERT_EQUAL_STRING_MESSAGE(input, printed_unformatted, "Unformatted array is not correct.");

+ 1 - 2
tests/print_object.c

@@ -29,7 +29,6 @@ static void assert_print_object(const char * const expected, const char * const
     unsigned char printed_unformatted[1024];
     unsigned char printed_formatted[1024];
 
-    const unsigned char *error_pointer;
     cJSON item[1];
 
     printbuffer formatted_buffer;
@@ -54,7 +53,7 @@ static void assert_print_object(const char * const expected, const char * const
     unformatted_buffer.noalloc = true;
 
     memset(item, 0, sizeof(item));
-    TEST_ASSERT_TRUE_MESSAGE(parse_object(item, &parsebuffer, &error_pointer, &global_hooks), "Failed to parse object.");
+    TEST_ASSERT_TRUE_MESSAGE(parse_object(item, &parsebuffer, &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.");

+ 1 - 2
tests/print_value.c

@@ -31,7 +31,6 @@
 static void assert_print_value(const char *input)
 {
     unsigned char printed[1024];
-    const unsigned char *error_pointer = NULL;
     cJSON item[1];
     printbuffer buffer;
     parse_buffer parsebuffer;
@@ -46,7 +45,7 @@ static void assert_print_value(const char *input)
 
     memset(item, 0, sizeof(item));
 
-    TEST_ASSERT_TRUE_MESSAGE(parse_value(item, &parsebuffer, &error_pointer, &global_hooks), "Failed to parse value.");
+    TEST_ASSERT_TRUE_MESSAGE(parse_value(item, &parsebuffer, &global_hooks), "Failed to parse value.");
 
     TEST_ASSERT_TRUE_MESSAGE(print_value(item, 0, false, &buffer, &global_hooks), "Failed to print value.");
     TEST_ASSERT_EQUAL_STRING_MESSAGE(input, buffer.buffer, "Printed value is not as expected.");