]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
mime: address scan-build warnings
authorVictor Julien <vjulien@oisf.net>
Fri, 21 Apr 2023 12:12:36 +0000 (14:12 +0200)
committerVictor Julien <vjulien@oisf.net>
Tue, 25 Apr 2023 09:36:37 +0000 (11:36 +0200)
util-decode-mime.c:189:31: warning: Use of memory after it is freed [unix.Malloc]
            lastSibling->next = entity->child;
            ~~~~~~~~~~~~~~~~~ ^
util-decode-mime.c:827:24: warning: Potential leak of memory pointed to by 'val' [unix.Malloc]
        state->hname = NULL;
                       ^~~~
/usr/lib/llvm-16/lib/clang/16/include/stddef.h:89:24: note: expanded from macro 'NULL'
 #  define NULL ((void*)0)
                       ^
2 warnings generated.

Improve error handling and add assert to avoid these warnings.

Bug: #3147.
(cherry picked from commit 9224b3435b94e848cc677103573439e505e808b3)

src/util-decode-mime.c

index a1ffdaea099093c7fd250910ac9956d276b08f58..8c45e2c0567a64753a26b2b7e770e1c9ad2ed206 100644 (file)
@@ -186,27 +186,21 @@ void MimeDecFreeEntity (MimeDecEntity *entity)
     MimeDecEntity *lastSibling = findLastSibling(entity);
     while (entity != NULL)
     {
-        /**
-         * Move child to next
-         * Transform tree into list
-         */
-        if (entity->child != NULL)
-        {
+        /* move child to next to transform the tree into a list */
+        if (entity->child != NULL) {
             lastSibling->next = entity->child;
+            entity->child = NULL;
             lastSibling = findLastSibling(lastSibling);
         }
 
-        /**
-         * Move to next element
-         */
-        MimeDecEntity *old = entity;
-        entity = entity->next;
-
-        MimeDecFreeField(old->field_list);
-        MimeDecFreeUrl(old->url_list);
-        SCFree(old->filename);
-
-        SCFree(old);
+        MimeDecEntity *next = entity->next;
+        DEBUG_VALIDATE_BUG_ON(
+                (next != NULL && entity == lastSibling) || (next == NULL && entity != lastSibling));
+        MimeDecFreeField(entity->field_list);
+        MimeDecFreeUrl(entity->url_list);
+        SCFree(entity->filename);
+        SCFree(entity);
+        entity = next;
     }
 }
 
@@ -429,9 +423,13 @@ MimeDecEntity * MimeDecAddEntity(MimeDecEntity *parent)
  * \param vlen Length of the value
  *
  * \return The field or NULL if the operation fails
+ *
+ * name and val are passed as ptr to ptr and each will be set to NULL
+ * only if the pointer is consumed. This gives the caller an easy way
+ * to free the memory if not consumed.
  */
-static MimeDecField * MimeDecFillField(MimeDecEntity *entity, uint8_t *name,
-        uint32_t nlen, const uint8_t *value, uint32_t vlen)
+static MimeDecField *MimeDecFillField(
+        MimeDecEntity *entity, uint8_t **name, uint32_t nlen, uint8_t **value, uint32_t vlen)
 {
     if (nlen == 0 && vlen == 0)
         return NULL;
@@ -442,18 +440,21 @@ static MimeDecField * MimeDecFillField(MimeDecEntity *entity, uint8_t *name,
     }
 
     if (nlen > 0) {
+        uint8_t *n = *name;
+
         /* convert to lowercase and store */
-        uint32_t u;
-        for (u = 0; u < nlen; u++)
-            name[u] = tolower(name[u]);
+        for (uint32_t u = 0; u < nlen; u++)
+            n[u] = u8_tolower(n[u]);
 
-        field->name = (uint8_t *)name;
+        field->name = (uint8_t *)n;
         field->name_len = nlen;
+        *name = NULL;
     }
 
     if (vlen > 0) {
-        field->value = (uint8_t *)value;
+        field->value = (uint8_t *)*value;
         field->value_len = vlen;
+        *value = NULL;
     }
 
     return field;
@@ -816,41 +817,38 @@ static uint8_t * GetToken(uint8_t *buf, uint32_t blen, const char *delims,
  */
 static int StoreMimeHeader(MimeDecParseState *state)
 {
-    int ret = MIME_DEC_OK, stored = 0;
-    uint8_t *val;
-    uint32_t vlen;
+    int ret = MIME_DEC_OK;
 
     /* Lets save the most recent header */
     if (state->hname != NULL || state->hvalue != NULL) {
         SCLogDebug("Storing last header");
-        val = GetFullValue(state->hvalue, &vlen);
+        uint32_t vlen;
+        uint8_t *val = GetFullValue(state->hvalue, &vlen);
         if (val != NULL) {
             if (state->hname == NULL) {
                 SCLogDebug("Error: Invalid parser state - header value without"
                         " name");
                 ret = MIME_DEC_ERR_PARSE;
+
             } else if (state->stack->top != NULL) {
                 /* Store each header name and value */
-                if (MimeDecFillField(state->stack->top->data, state->hname, state->hlen, val,
+                if (MimeDecFillField(state->stack->top->data, &state->hname, state->hlen, &val,
                             vlen) == NULL) {
                     ret = MIME_DEC_ERR_MEM;
-                } else {
-                    stored = 1;
                 }
             } else {
                 SCLogDebug("Error: Stack pointer missing");
                 ret = MIME_DEC_ERR_DATA;
             }
-        } else if (state->hvalue != NULL) {
-            /* Memory allocation must have failed since val is NULL */
-            ret = MIME_DEC_ERR_MEM;
+        } else {
+            if (state->hvalue != NULL) {
+                /* Memory allocation must have failed since val is NULL */
+                ret = MIME_DEC_ERR_MEM;
+            }
         }
 
-        /* Do cleanup here */
-        if (!stored) {
-            SCFree(state->hname);
-            SCFree(val);
-        }
+        SCFree(val);
+        SCFree(state->hname);
         state->hname = NULL;
         FreeDataValue(state->hvalue);
         state->hvalue = NULL;