diff options
author | Stefan Bühler <stbuehler@web.de> | 2017-05-06 11:42:56 +0200 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2017-05-14 00:09:23 -0400 |
commit | 97526207920ed5d18bcabb8af66a058790ee06a8 (patch) | |
tree | 320717da638c1530a60acd92b67a36a2a6be36ba /src/configparser.y | |
parent | a48d65c8a52ece5ab3f6339ac7bd619dc02571b7 (diff) | |
download | lighttpd-git-97526207920ed5d18bcabb8af66a058790ee06a8.tar.gz |
[core] configparser: fix resource handling in error cases (fixes #2809)
- lemon never calls the destructor for variables on the RHS, make sure
to manually clean up
- outside `if (ctx->ok) { }` always check for NULL pointers, i.e:
- if (x) x->free(x)
- buffer_free and array_free check for NULL on their own
- cleanup RHS variables below `if (ctx->ok) { }` at the bottom
- set variables to NULL before if ownership gets passed on
- move some buffers instead of copying them
x-ref:
"Memory corruption in yy_reduce (configparser.y), SIGSEGV"
https://redmine.lighttpd.net/issues/2809
Diffstat (limited to 'src/configparser.y')
-rw-r--r-- | src/configparser.y | 88 |
1 files changed, 50 insertions, 38 deletions
diff --git a/src/configparser.y b/src/configparser.y index eddc6694..ad8b8ce9 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -197,12 +197,12 @@ varline ::= key(A) ASSIGN expression(B). { ctx->current->context_ndx, ctx->current->key->ptr, B->key->ptr); ctx->ok = 0; - B->free(B); - B = NULL; } } buffer_free(A); A = NULL; + if (B) B->free(B); + B = NULL; } varline ::= key(A) FORCE_ASSIGN expression(B). { @@ -220,6 +220,8 @@ varline ::= key(A) FORCE_ASSIGN expression(B). { } buffer_free(A); A = NULL; + if (B) B->free(B); + B = NULL; } varline ::= key(A) APPEND expression(B). { @@ -241,40 +243,43 @@ varline ::= key(A) APPEND expression(B). { buffer_copy_buffer(du->key, A); array_insert_unique(ctx->current->value, du); } - B->free(B); } else { buffer_copy_buffer(B->key, A); array_insert_unique(ctx->current->value, B); + B = NULL; } - buffer_free(A); - A = NULL; - B = NULL; } + buffer_free(A); + A = NULL; + if (B) B->free(B); + B = NULL; } key(A) ::= LKEY(B). { if (strchr(B->ptr, '.') == NULL) { A = buffer_init_string("var."); buffer_append_string_buffer(A, B); - buffer_free(B); - B = NULL; } else { A = B; B = NULL; } + buffer_free(B); + B = NULL; } expression(A) ::= expression(B) PLUS value(C). { A = NULL; if (ctx->ok) { A = configparser_merge_data(B, C); + B = NULL; if (NULL == A) { ctx->ok = 0; } - B = NULL; - C->free(C); - C = NULL; } + if (B) B->free(B); + B = NULL; + if (C) C->free(C); + C = NULL; } expression(A) ::= value(B). { @@ -302,14 +307,14 @@ value(A) ::= key(B). { fprintf(stderr, "Undefined config variable: %s\n", B->ptr); ctx->ok = 0; } - buffer_free(B); - B = NULL; } + buffer_free(B); + B = NULL; } value(A) ::= STRING(B). { A = (data_unset *)data_string_init(); - buffer_copy_buffer(((data_string *)(A))->value, B); + buffer_move(((data_string *)(A))->value, B); buffer_free(B); B = NULL; } @@ -353,13 +358,15 @@ aelements(A) ::= aelements(C) COMMA aelement(B). { fprintf(stderr, "Error: duplicate array-key: %s. Please get rid of the duplicate entry.\n", B->key->ptr); ctx->ok = 0; - B->free(B); - B = NULL; } A = C; C = NULL; } + array_free(C); + C = NULL; + if (B) B->free(B); + B = NULL; } aelements(A) ::= aelements(C) COMMA. { @@ -374,6 +381,8 @@ aelements(A) ::= aelement(B). { array_insert_unique(A, B); B = NULL; } + if (B) B->free(B); + B = NULL; } aelement(A) ::= expression(B). { @@ -384,12 +393,14 @@ aelement(A) ::= stringop(B) ARRAY_ASSIGN expression(C). { A = NULL; if (ctx->ok) { buffer_copy_buffer(C->key, B); - buffer_free(B); - B = NULL; A = C; C = NULL; } + if (C) C->free(C); + C = NULL; + buffer_free(B); + B = NULL; } eols ::= EOL. @@ -422,9 +433,9 @@ condlines(A) ::= condlines(B) eols ELSE condline(C). { C->prev = B; B->next = C; A = C; - B = NULL; - C = NULL; } + B = NULL; + C = NULL; } condlines(A) ::= condlines(B) eols ELSE cond_else(C). { @@ -482,9 +493,9 @@ condlines(A) ::= condlines(B) eols ELSE cond_else(C). { } A = C; - B = NULL; - C = NULL; } + B = NULL; + C = NULL; } condlines(A) ::= condline(B). { @@ -522,7 +533,7 @@ cond_else(A) ::= context_else LCURLY metalines RCURLY. { context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expression(D). { data_config *dc; - buffer *b, *rvalue, *op; + buffer *b = NULL, *rvalue, *op = NULL; if (ctx->ok && D->type != TYPE_STRING) { fprintf(stderr, "rvalue must be string"); @@ -734,16 +745,16 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio dc->free((data_unset*) dc); } } - - buffer_free(b); - buffer_free(op); - buffer_free(B); - B = NULL; - buffer_free(C); - C = NULL; - D->free(D); - D = NULL; } + + buffer_free(b); + buffer_free(op); + buffer_free(B); + B = NULL; + buffer_free(C); + C = NULL; + if (D) D->free(D); + D = NULL; } context_else ::= . { @@ -774,7 +785,8 @@ stringop(A) ::= expression(B). { A = NULL; if (ctx->ok) { if (B->type == TYPE_STRING) { - A = buffer_init_buffer(((data_string*)B)->value); + A = ((data_string*)B)->value; + ((data_string*)B)->value = NULL; } else if (B->type == TYPE_INTEGER) { A = buffer_init(); buffer_copy_int(A, ((data_integer *)B)->value); @@ -783,7 +795,7 @@ stringop(A) ::= expression(B). { ctx->ok = 0; } } - B->free(B); + if (B) B->free(B); B = NULL; } @@ -792,9 +804,9 @@ include ::= INCLUDE stringop(A). { if (0 != config_parse_file(ctx->srv, ctx, A->ptr)) { ctx->ok = 0; } - buffer_free(A); - A = NULL; } + buffer_free(A); + A = NULL; } include_shell ::= INCLUDE_SHELL stringop(A). { @@ -802,7 +814,7 @@ include_shell ::= INCLUDE_SHELL stringop(A). { if (0 != config_parse_cmd(ctx->srv, ctx, A->ptr)) { ctx->ok = 0; } - buffer_free(A); - A = NULL; } + buffer_free(A); + A = NULL; } |