mirror of
https://github.com/DaveGamble/cJSON.git
synced 2023-08-10 21:13:26 +03:00
Merge pull request #100 from DaveGamble/goto-fail
Use goto fail for error handling and fix some memory leaks on the way
This commit is contained in:
commit
7119a16b5f
115
cJSON.c
115
cJSON.c
@ -521,7 +521,7 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
if (*str != '\"')
|
if (*str != '\"')
|
||||||
{
|
{
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((*end_ptr != '\"') && *end_ptr)
|
while ((*end_ptr != '\"') && *end_ptr)
|
||||||
@ -531,7 +531,7 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
if (*end_ptr == '\0')
|
if (*end_ptr == '\0')
|
||||||
{
|
{
|
||||||
/* prevent buffer overflow when last input character is a backslash */
|
/* prevent buffer overflow when last input character is a backslash */
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Skip escaped quotes. */
|
/* Skip escaped quotes. */
|
||||||
end_ptr++;
|
end_ptr++;
|
||||||
@ -543,7 +543,7 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
out = (unsigned char*)cJSON_malloc(len + 1);
|
out = (unsigned char*)cJSON_malloc(len + 1);
|
||||||
if (!out)
|
if (!out)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
item->valuestring = (char*)out; /* assign here so out will be deleted during cJSON_Delete() later */
|
item->valuestring = (char*)out; /* assign here so out will be deleted during cJSON_Delete() later */
|
||||||
item->type = cJSON_String;
|
item->type = cJSON_String;
|
||||||
@ -591,13 +591,13 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
{
|
{
|
||||||
/* invalid */
|
/* invalid */
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* check for invalid. */
|
/* check for invalid. */
|
||||||
if (((uc >= 0xDC00) && (uc <= 0xDFFF)) || (uc == 0))
|
if (((uc >= 0xDC00) && (uc <= 0xDFFF)) || (uc == 0))
|
||||||
{
|
{
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UTF16 surrogate pairs. */
|
/* UTF16 surrogate pairs. */
|
||||||
@ -607,13 +607,13 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
{
|
{
|
||||||
/* invalid */
|
/* invalid */
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((ptr[1] != '\\') || (ptr[2] != 'u'))
|
if ((ptr[1] != '\\') || (ptr[2] != 'u'))
|
||||||
{
|
{
|
||||||
/* missing second-half of surrogate. */
|
/* missing second-half of surrogate. */
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
uc2 = parse_hex4(ptr + 3);
|
uc2 = parse_hex4(ptr + 3);
|
||||||
ptr += 6; /* \uXXXX */
|
ptr += 6; /* \uXXXX */
|
||||||
@ -621,7 +621,7 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
{
|
{
|
||||||
/* invalid second-half of surrogate. */
|
/* invalid second-half of surrogate. */
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* calculate unicode codepoint from the surrogate pair */
|
/* calculate unicode codepoint from the surrogate pair */
|
||||||
uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
|
uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
|
||||||
@ -668,13 +668,13 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
ptr2 += len;
|
ptr2 += len;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*ep = str;
|
*ep = str;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
@ -686,6 +686,14 @@ static const unsigned char *parse_string(cJSON *item, const unsigned char *str,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (out != NULL)
|
||||||
|
{
|
||||||
|
cJSON_free(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render the cstring provided to an escaped version that can be printed. */
|
/* Render the cstring provided to an escaped version that can be printed. */
|
||||||
@ -1119,7 +1127,7 @@ static const unsigned char *parse_array(cJSON *item, const unsigned char *value,
|
|||||||
{
|
{
|
||||||
/* not an array! */
|
/* not an array! */
|
||||||
*ep = value;
|
*ep = value;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->type = cJSON_Array;
|
item->type = cJSON_Array;
|
||||||
@ -1134,13 +1142,13 @@ static const unsigned char *parse_array(cJSON *item, const unsigned char *value,
|
|||||||
if (!item->child)
|
if (!item->child)
|
||||||
{
|
{
|
||||||
/* memory fail */
|
/* memory fail */
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* skip any spacing, get the value. */
|
/* skip any spacing, get the value. */
|
||||||
value = skip(parse_value(child, skip(value), ep));
|
value = skip(parse_value(child, skip(value), ep));
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loop through the comma separated array elements */
|
/* loop through the comma separated array elements */
|
||||||
@ -1150,7 +1158,7 @@ static const unsigned char *parse_array(cJSON *item, const unsigned char *value,
|
|||||||
if (!(new_item = cJSON_New_Item()))
|
if (!(new_item = cJSON_New_Item()))
|
||||||
{
|
{
|
||||||
/* memory fail */
|
/* memory fail */
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* add new item to end of the linked list */
|
/* add new item to end of the linked list */
|
||||||
child->next = new_item;
|
child->next = new_item;
|
||||||
@ -1162,7 +1170,7 @@ static const unsigned char *parse_array(cJSON *item, const unsigned char *value,
|
|||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
/* memory fail */
|
/* memory fail */
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,6 +1183,13 @@ static const unsigned char *parse_array(cJSON *item, const unsigned char *value,
|
|||||||
/* malformed. */
|
/* malformed. */
|
||||||
*ep = value;
|
*ep = value;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (item->child != NULL)
|
||||||
|
{
|
||||||
|
cJSON_Delete(item->child);
|
||||||
|
item->child = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1355,7 +1370,7 @@ static const unsigned char *parse_object(cJSON *item, const unsigned char *value
|
|||||||
{
|
{
|
||||||
/* not an object! */
|
/* not an object! */
|
||||||
*ep = value;
|
*ep = value;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->type = cJSON_Object;
|
item->type = cJSON_Object;
|
||||||
@ -1370,13 +1385,13 @@ static const unsigned char *parse_object(cJSON *item, const unsigned char *value
|
|||||||
item->child = child;
|
item->child = child;
|
||||||
if (!item->child)
|
if (!item->child)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* parse first key */
|
/* parse first key */
|
||||||
value = skip(parse_string(child, skip(value), ep));
|
value = skip(parse_string(child, skip(value), ep));
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* use string as key, not value */
|
/* use string as key, not value */
|
||||||
child->string = child->valuestring;
|
child->string = child->valuestring;
|
||||||
@ -1386,13 +1401,13 @@ static const unsigned char *parse_object(cJSON *item, const unsigned char *value
|
|||||||
{
|
{
|
||||||
/* invalid object. */
|
/* invalid object. */
|
||||||
*ep = value;
|
*ep = value;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* skip any spacing, get the value. */
|
/* skip any spacing, get the value. */
|
||||||
value = skip(parse_value(child, skip(value + 1), ep));
|
value = skip(parse_value(child, skip(value + 1), ep));
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*value == ',')
|
while (*value == ',')
|
||||||
@ -1401,7 +1416,7 @@ static const unsigned char *parse_object(cJSON *item, const unsigned char *value
|
|||||||
if (!(new_item = cJSON_New_Item()))
|
if (!(new_item = cJSON_New_Item()))
|
||||||
{
|
{
|
||||||
/* memory fail */
|
/* memory fail */
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* add to linked list */
|
/* add to linked list */
|
||||||
child->next = new_item;
|
child->next = new_item;
|
||||||
@ -1411,7 +1426,7 @@ static const unsigned char *parse_object(cJSON *item, const unsigned char *value
|
|||||||
value = skip(parse_string(child, skip(value + 1), ep));
|
value = skip(parse_string(child, skip(value + 1), ep));
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use string as key, not value */
|
/* use string as key, not value */
|
||||||
@ -1422,13 +1437,13 @@ static const unsigned char *parse_object(cJSON *item, const unsigned char *value
|
|||||||
{
|
{
|
||||||
/* invalid object. */
|
/* invalid object. */
|
||||||
*ep = value;
|
*ep = value;
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* skip any spacing, get the value. */
|
/* skip any spacing, get the value. */
|
||||||
value = skip(parse_value(child, skip(value + 1), ep));
|
value = skip(parse_value(child, skip(value + 1), ep));
|
||||||
if (!value)
|
if (!value)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* end of object */
|
/* end of object */
|
||||||
@ -1439,6 +1454,14 @@ static const unsigned char *parse_object(cJSON *item, const unsigned char *value
|
|||||||
|
|
||||||
/* malformed */
|
/* malformed */
|
||||||
*ep = value;
|
*ep = value;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (item->child != NULL)
|
||||||
|
{
|
||||||
|
cJSON_Delete(child);
|
||||||
|
item->child = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2293,20 +2316,20 @@ cJSON *cJSON_CreateStringArray(const char **strings, int count)
|
|||||||
cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
|
cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
|
||||||
{
|
{
|
||||||
cJSON *newitem = NULL;
|
cJSON *newitem = NULL;
|
||||||
cJSON *cptr = NULL;
|
cJSON *child = NULL;
|
||||||
cJSON *nptr = NULL;
|
cJSON *next = NULL;
|
||||||
cJSON *newchild = NULL;
|
cJSON *newchild = NULL;
|
||||||
|
|
||||||
/* Bail on bad ptr */
|
/* Bail on bad ptr */
|
||||||
if (!item)
|
if (!item)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Create new item */
|
/* Create new item */
|
||||||
newitem = cJSON_New_Item();
|
newitem = cJSON_New_Item();
|
||||||
if (!newitem)
|
if (!newitem)
|
||||||
{
|
{
|
||||||
return NULL;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Copy over all vars */
|
/* Copy over all vars */
|
||||||
newitem->type = item->type & (~cJSON_IsReference);
|
newitem->type = item->type & (~cJSON_IsReference);
|
||||||
@ -2317,8 +2340,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
|
|||||||
newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring);
|
newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring);
|
||||||
if (!newitem->valuestring)
|
if (!newitem->valuestring)
|
||||||
{
|
{
|
||||||
cJSON_Delete(newitem);
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (item->string)
|
if (item->string)
|
||||||
@ -2326,8 +2348,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
|
|||||||
newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string);
|
newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string);
|
||||||
if (!newitem->string)
|
if (!newitem->string)
|
||||||
{
|
{
|
||||||
cJSON_Delete(newitem);
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If non-recursive, then we're done! */
|
/* If non-recursive, then we're done! */
|
||||||
@ -2336,31 +2357,39 @@ cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
|
|||||||
return newitem;
|
return newitem;
|
||||||
}
|
}
|
||||||
/* Walk the ->next chain for the child. */
|
/* Walk the ->next chain for the child. */
|
||||||
cptr = item->child;
|
child = item->child;
|
||||||
while (cptr)
|
while (child != NULL)
|
||||||
{
|
{
|
||||||
newchild = cJSON_Duplicate(cptr, 1); /* Duplicate (with recurse) each item in the ->next chain */
|
newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
|
||||||
if (!newchild)
|
if (!newchild)
|
||||||
{
|
{
|
||||||
cJSON_Delete(newitem);
|
goto fail;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
if (nptr)
|
if (next != NULL)
|
||||||
{
|
{
|
||||||
/* If newitem->child already set, then crosswire ->prev and ->next and move on */
|
/* If newitem->child already set, then crosswire ->prev and ->next and move on */
|
||||||
nptr->next = newchild;
|
next->next = newchild;
|
||||||
newchild->prev = nptr;
|
newchild->prev = next;
|
||||||
nptr = newchild;
|
next = newchild;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Set newitem->child and move to it */
|
/* Set newitem->child and move to it */
|
||||||
newitem->child = newchild; nptr = newchild;
|
newitem->child = newchild;
|
||||||
|
next = newchild;
|
||||||
}
|
}
|
||||||
cptr = cptr->next;
|
child = child->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return newitem;
|
return newitem;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (newitem != NULL)
|
||||||
|
{
|
||||||
|
cJSON_Delete(newitem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cJSON_Minify(char *json)
|
void cJSON_Minify(char *json)
|
||||||
|
2
test.c
2
test.c
@ -114,7 +114,7 @@ static int print_preallocated(cJSON *root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* create buffer to fail */
|
/* create buffer to fail */
|
||||||
len_fail = strlen(out);
|
len_fail = strlen(out) + sizeof('\0');
|
||||||
buf_fail = (char*)malloc(len_fail);
|
buf_fail = (char*)malloc(len_fail);
|
||||||
if (buf_fail == NULL)
|
if (buf_fail == NULL)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user