fixes memory leak in davqlparser

Thu, 31 Aug 2017 20:01:15 +0200

author
Mike Becker <universe@uap-core.de>
date
Thu, 31 Aug 2017 20:01:15 +0200
changeset 291
8828260d2fd8
parent 290
1e3e374d9386
child 292
0a47ffc8b73b

fixes memory leak in davqlparser

libidav/davqlparser.c file | annotate | diff | comparison | revisions
--- a/libidav/davqlparser.c	Thu Aug 31 13:10:55 2017 +0200
+++ b/libidav/davqlparser.c	Thu Aug 31 20:01:15 2017 +0200
@@ -419,26 +419,28 @@
         ln, pn).ptr;
 }
 
-// TODO: this macro results in a memory leak - we return without freeing memory
 #define dqlsec_alloc_failed(ptr, stmt)                                  \
-                    if (!(ptr)) {                                       \
+                    if (!(ptr)) do {                                    \
                         (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;  \
                         return 0;                                       \
-                    }
-#define dqlsec_malloc(stmt, ptr, type)  ptr = malloc(sizeof(type));     \
-                                        dqlsec_alloc_failed(ptr, stmt);
-#define dqlsec_mallocz(stmt, ptr, type) ptr = calloc(1, sizeof(type));  \
-                                        dqlsec_alloc_failed(ptr, stmt);
+                    } while(0)
+#define dqlsec_malloc(stmt, ptr, type) \
+        dqlsec_alloc_failed(ptr = malloc(sizeof(type)), stmt)
+#define dqlsec_mallocz(stmt, ptr, type) \
+        dqlsec_alloc_failed(ptr = calloc(1, sizeof(type)), stmt)
 
-#define dqlsec_list_append(stmt, list, data)                    \
-    {                                                           \
+#define dqlsec_list_append_or_free(stmt, list, data)            \
+    do {                                                        \
         UcxList *_dqlsecbak_ = list;                            \
         list = ucx_list_append(list, data);                     \
         if (!list) {                                            \
+            free(data);                                         \
+            data = NULL;                                        \
             (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;      \
             list = _dqlsecbak_;                                 \
+            return 0;                                           \
         }                                                       \
-    }
+    } while(0)
 
 // special symbols are single tokens - the % sign MUST NOT be a special symbol
 static const char *special_token_symbols = ",()+-*/&|^~=!<>";
@@ -531,10 +533,10 @@
 }
 
 static UcxList* dav_parse_tokenize(sstr_t src) {
-#define alloc_token token = malloc(sizeof(DavQLToken));\
-        if(!token) {ucx_list_free(tokens); return NULL;}
-#define add_token tokens = dav_parse_add_token(tokens, token); \
-        if(!tokens) {return NULL;}
+#define alloc_token() do {token = malloc(sizeof(DavQLToken));\
+        if(!token) {ucx_list_free(tokens); return NULL;}} while(0)
+#define add_token() do {tokens = dav_parse_add_token(tokens, token); \
+        if(!tokens) {return NULL;}} while(0)
     UcxList *tokens = NULL;
     
     DavQLToken *token = NULL;
@@ -551,7 +553,7 @@
                 } else {
                     // add quoted token to list
                     token->value.length++;
-                    add_token
+                    add_token();
                     token = NULL;
                     insequence = '\0';
                 }
@@ -559,9 +561,9 @@
                 insequence = src.ptr[i];
                 // always create new token for quoted strings
                 if (token) {
-                    add_token
+                    add_token();
                 }
-                alloc_token
+                alloc_token();
                 token->value.ptr = src.ptr + i;
                 token->value.length = 1;
             } else {
@@ -573,26 +575,26 @@
         } else if (isspace(src.ptr[i])) {
             // add token before spaces to list (if any)
             if (token) {
-                add_token
+                add_token();
                 token = NULL;
             }
         } else if (strchr(special_token_symbols, src.ptr[i])) {
             // add token before special symbol to list (if any)
             if (token) {
-                add_token
+                add_token();
                 token = NULL;
             }
             // add special symbol as single token to list
-            alloc_token
+            alloc_token();
             token->value.ptr = src.ptr + i;
             token->value.length = 1;
-            add_token
+            add_token();
             // set tokenizer ready to read more tokens
             token = NULL;
         } else {
             // if this is a new token, create memory for it
             if (!token) {
-                alloc_token
+                alloc_token();
                 token->value.ptr = src.ptr + i;
                 token->value.length = 0;
             }
@@ -602,10 +604,10 @@
     }
     
     if (token) {
-        add_token
+        add_token();
     }
     
-    alloc_token
+    alloc_token();
     token->tokenclass = DAVQL_TOKEN_END;
     token->value = S("");
     UcxList *ret = ucx_list_append(tokens, token);
@@ -998,10 +1000,10 @@
     if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "-")) {
         DavQLField *field;
         dqlsec_malloc(stmt, field, DavQLField);
+        dqlsec_list_append_or_free(stmt, stmt->fields, field);
         dqlsec_mallocz(stmt, field->expr, DavQLExpression);
         field->expr->type = DAVQL_IDENTIFIER;
         field->expr->srctext = field->name = token_sstr(token);
-        dqlsec_list_append(stmt, stmt->fields, field);
         return 1;
     }
     
@@ -1009,10 +1011,10 @@
     if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) {
         DavQLField *field;
         dqlsec_malloc(stmt, field, DavQLField);
+        dqlsec_list_append_or_free(stmt, stmt->fields, field);
         dqlsec_mallocz(stmt, field->expr, DavQLExpression);
         field->expr->type = DAVQL_IDENTIFIER;
         field->expr->srctext = field->name = token_sstr(token);
-        dqlsec_list_append(stmt, stmt->fields, field);
         
         int total_consumed = 0;
         int consumed = 1;
@@ -1029,7 +1031,7 @@
                     DavQLField *field;
                     dqlsec_malloc(stmt, field, DavQLField);
                     memcpy(field, &localfield, sizeof(DavQLField));
-                    dqlsec_list_append(stmt, stmt->fields, field);
+                    dqlsec_list_append_or_free(stmt, stmt->fields, field);
                 }                
             } else {
                 consumed = 0;
@@ -1050,7 +1052,7 @@
                 DavQLField *field;
                 dqlsec_malloc(stmt, field, DavQLField);
                 memcpy(field, &localfield, sizeof(DavQLField));
-                dqlsec_list_append(stmt, stmt->fields, field);
+                dqlsec_list_append_or_free(stmt, stmt->fields, field);
                 token = ucx_list_get(token, consumed);
                 total_consumed += consumed;
             } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)
@@ -1063,7 +1065,7 @@
                 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
                 field->expr->type = DAVQL_IDENTIFIER;
                 field->expr->srctext = field->name = token_sstr(token);
-                dqlsec_list_append(stmt, stmt->fields, field);
+                dqlsec_list_append_or_free(stmt, stmt->fields, field);
 
                 consumed = 1;
                 total_consumed++;
@@ -1447,7 +1449,7 @@
         DavQLOrderCriterion *criterion;
         dqlsec_malloc(stmt, criterion, DavQLOrderCriterion);
         memcpy(criterion, &crit, sizeof(DavQLOrderCriterion));
-        dqlsec_list_append(stmt, stmt->orderby, criterion);
+        dqlsec_list_append_or_free(stmt, stmt->orderby, criterion);
         
         if (token_is(token, DAVQL_TOKEN_COMMA)) {
             total_consumed++;

mercurial