secured ucx_list_append calls against OOM

Fri, 05 Jun 2015 10:44:21 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 05 Jun 2015 10:44:21 +0200
changeset 132
8c9b84f37af5
parent 131
32e7b3e6b482
child 133
8c37028f5024

secured ucx_list_append calls against OOM

libidav/davqlparser.c file | annotate | diff | comparison | revisions
--- a/libidav/davqlparser.c	Fri Jun 05 10:10:14 2015 +0200
+++ b/libidav/davqlparser.c	Fri Jun 05 10:44:21 2015 +0200
@@ -429,6 +429,15 @@
 #define dqlsec_mallocz(stmt, ptr, type) ptr = calloc(1, sizeof(type));  \
                                         dqlsec_alloc_failed(ptr, stmt);
 
+#define dqlsec_list_append(stmt, list, data)                    \
+    {                                                           \
+        UcxList *_dqlsecbak_ = list;                            \
+        list = ucx_list_append(list, data);                     \
+        if (!list) {                                            \
+            (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;      \
+            list = _dqlsecbak_;                                 \
+        }                                                       \
+    }
 
 // special symbols are single tokens - the % sign MUST NOT be a special symbol
 static const char *special_token_symbols = ",()+-*/&|^~=!<>";
@@ -503,12 +512,20 @@
     }
     
     
-    return ucx_list_append(tokenlist, token);
+    UcxList *ret = ucx_list_append(tokenlist, token);
+    if (ret) {
+        return ret;
+    } else {
+        ucx_list_free(tokenlist);
+        return NULL;
+    }
 }
 
 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;}
     UcxList *tokens = NULL;
     
     DavQLToken *token = NULL;
@@ -525,7 +542,7 @@
                 } else {
                     // add quoted token to list
                     token->value.length++;
-                    tokens = dav_parse_add_token(tokens, token);
+                    add_token
                     token = NULL;
                     insequence = '\0';
                 }
@@ -533,7 +550,7 @@
                 insequence = src.ptr[i];
                 // always create new token for quoted strings
                 if (token) {
-                    tokens = dav_parse_add_token(tokens, token);
+                    add_token
                 }
                 alloc_token
                 token->value.ptr = src.ptr + i;
@@ -547,20 +564,20 @@
         } else if (isspace(src.ptr[i])) {
             // add token before spaces to list (if any)
             if (token) {
-                tokens = dav_parse_add_token(tokens, 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) {
-                tokens = dav_parse_add_token(tokens, token);
+                add_token
                 token = NULL;
             }
             // add special symbol as single token to list
             alloc_token
             token->value.ptr = src.ptr + i;
             token->value.length = 1;
-            tokens = dav_parse_add_token(tokens, token);
+            add_token
             // set tokenizer ready to read more tokens
             token = NULL;
         } else {
@@ -576,14 +593,21 @@
     }
     
     if (token) {
-        tokens = dav_parse_add_token(tokens, token);
+        add_token
     }
     
     alloc_token
     token->tokenclass = DAVQL_TOKEN_END;
     token->value = S("");
-    return ucx_list_append(tokens, token);
+    UcxList *ret = ucx_list_append(tokens, token);
+    if (ret) {
+        return ret;
+    } else {
+        ucx_list_free(tokens);
+        return NULL;
+    }
 #undef alloc_token
+#undef add_token
 }
 
 static void dav_free_expression(DavQLExpression *expr) {
@@ -968,7 +992,7 @@
         dqlsec_mallocz(stmt, field->expr, DavQLExpression);
         field->expr->type = DAVQL_IDENTIFIER;
         field->expr->srctext = field->name = token_sstr(token);
-        stmt->fields = ucx_list_append(stmt->fields, field);
+        dqlsec_list_append(stmt, stmt->fields, field);
         return 1;
     }
     
@@ -979,7 +1003,7 @@
         dqlsec_mallocz(stmt, field->expr, DavQLExpression);
         field->expr->type = DAVQL_IDENTIFIER;
         field->expr->srctext = field->name = token_sstr(token);
-        stmt->fields = ucx_list_append(stmt->fields, field);
+        dqlsec_list_append(stmt, stmt->fields, field);
         
         int total_consumed = 0;
         int consumed = 1;
@@ -996,7 +1020,7 @@
                     DavQLField *field;
                     dqlsec_malloc(stmt, field, DavQLField);
                     memcpy(field, &localfield, sizeof(DavQLField));
-                    stmt->fields = ucx_list_append(stmt->fields, field);
+                    dqlsec_list_append(stmt, stmt->fields, field);
                 }                
             } else {
                 consumed = 0;
@@ -1017,7 +1041,7 @@
                 DavQLField *field;
                 dqlsec_malloc(stmt, field, DavQLField);
                 memcpy(field, &localfield, sizeof(DavQLField));
-                stmt->fields = ucx_list_append(stmt->fields, field);
+                dqlsec_list_append(stmt, stmt->fields, field);
                 token = ucx_list_get(token, consumed);
                 total_consumed += consumed;
             } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)
@@ -1030,7 +1054,7 @@
                 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
                 field->expr->type = DAVQL_IDENTIFIER;
                 field->expr->srctext = field->name = token_sstr(token);
-                stmt->fields = ucx_list_append(stmt->fields, field);
+                dqlsec_list_append(stmt, stmt->fields, field);
 
                 consumed = 1;
                 total_consumed++;
@@ -1414,7 +1438,7 @@
         DavQLOrderCriterion *criterion;
         dqlsec_malloc(stmt, criterion, DavQLOrderCriterion);
         memcpy(criterion, &crit, sizeof(DavQLOrderCriterion));
-        stmt->orderby = ucx_list_append(stmt->orderby, criterion);
+        dqlsec_list_append(stmt, stmt->orderby, criterion);
         
         if (token_is(token, DAVQL_TOKEN_COMMA)) {
             total_consumed++;
@@ -1555,27 +1579,31 @@
     // save trimmed source text
     stmt->srctext = sstrtrim(srctext);
     
-    // tokenization
-    UcxList* tokens = dav_parse_tokenize(stmt->srctext);
-    
-    if (tokens) {
-        // use first token to determine query type
-        
-        if (tokenvalue_is(tokens, "select")) {
-            dav_parse_select_statement(stmt, tokens->next);
-        } else if (tokenvalue_is(tokens, "set")) {
-            dav_parse_set_statement(stmt, tokens->next);
+    if (stmt->srctext.length) {   
+        // tokenization
+        UcxList* tokens = dav_parse_tokenize(stmt->srctext);
+
+        if (tokens) {
+            // use first token to determine query type
+
+            if (tokenvalue_is(tokens, "select")) {
+                dav_parse_select_statement(stmt, tokens->next);
+            } else if (tokenvalue_is(tokens, "set")) {
+                dav_parse_set_statement(stmt, tokens->next);
+            } else {
+                stmt->type = DAVQL_ERROR;
+                stmt->errorcode = DAVQL_ERROR_INVALID;
+                stmt->errormessage = strdup(_error_invalid);
+            }
+
+            // free token data
+            UCX_FOREACH(token, tokens) {
+                free(token->data);
+            }
+            ucx_list_free(tokens);
         } else {
-            stmt->type = DAVQL_ERROR;
-            stmt->errorcode = DAVQL_ERROR_INVALID;
-            stmt->errormessage = strdup(_error_invalid);
+            stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
         }
-        
-        // free token data
-        UCX_FOREACH(token, tokens) {
-            free(token->data);
-        }
-        ucx_list_free(tokens);
     } else {
         stmt->type = DAVQL_ERROR;
         stmt->errorcode = DAVQL_ERROR_INVALID;

mercurial