Ver código fonte

parse_string: goto fail error handling

Makes the control flow easier to reason about and fixes a few potential
memory leaks.
Max Bruckner 8 anos atrás
pai
commit
8656386c4f
1 arquivos alterados com 18 adições e 10 exclusões
  1. 18 10
      cJSON.c

+ 18 - 10
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. */