Fri, 05 Jun 2015 10:44:21 +0200
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;