parse_string: goto fail error handling

Makes the control flow easier to reason about and fixes a few potential
memory leaks.
This commit is contained in:
Max Bruckner 2017-02-06 18:37:00 +01:00
parent c866abd842
commit 8656386c4f

28
cJSON.c
View File

@ -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. */