# HG changeset patch # User Mike Becker # Date 1504202475 -7200 # Node ID 8828260d2fd84f2dd08e740b7b0912927714244f # Parent 1e3e374d938660df549bfeb10b2b9d13631fede6 fixes memory leak in davqlparser diff -r 1e3e374d9386 -r 8828260d2fd8 libidav/davqlparser.c --- 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++;