From ce24523b59ed97a42b2e446036b70f490400688f Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sun, 9 Oct 2016 09:20:37 -0400 Subject: [PATCH] [core] restrict where config "else" clauses occur (#1268) (improve validation) x-ref: "condition should be optional in "else" clause in configuration file" https://redmine.lighttpd.net/issues/1268 --- src/configparser.y | 87 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 9 deletions(-) diff --git a/src/configparser.y b/src/configparser.y index 9d2ab190..cdffd043 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -162,6 +162,7 @@ metaline ::= EOL. %type expression {data_unset *} %type aelement {data_unset *} %type condline {data_config *} +%type cond_else {data_config *} %type condlines {data_config *} %type aelements {array *} %type array {array *} @@ -410,6 +411,66 @@ condlines(A) ::= condlines(B) eols ELSE condline(C). { } } +condlines(A) ::= condlines(B) eols ELSE cond_else(C). { + A = NULL; + if (ctx->ok) { + if (B->context_ndx >= C->context_ndx) { + fprintf(stderr, "unreachable else condition\n"); + ctx->ok = 0; + } + if (B->cond == CONFIG_COND_ELSE) { + fprintf(stderr, "unreachable condition following else catch-all\n"); + ctx->ok = 0; + } + } + if (ctx->ok) { + size_t pos; + data_config *dc; + dc = (data_config *)array_extract_element(ctx->all_configs, C->key->ptr); + force_assert(C == dc); + buffer_copy_buffer(C->key, B->key); + /*buffer_copy_buffer(C->comp_key, B->comp_key);*/ + /*C->string = buffer_init_buffer(B->string);*/ + pos = buffer_string_length(C->key)-buffer_string_length(B->string)-2; + switch(B->cond) { + case CONFIG_COND_NE: + C->key->ptr[pos] = '='; /* opposite cond */ + /*buffer_copy_string_len(C->op, CONST_STR_LEN("=="));*/ + break; + case CONFIG_COND_EQ: + C->key->ptr[pos] = '!'; /* opposite cond */ + /*buffer_copy_string_len(C->op, CONST_STR_LEN("!="));*/ + break; + case CONFIG_COND_NOMATCH: + C->key->ptr[pos] = '='; /* opposite cond */ + /*buffer_copy_string_len(C->op, CONST_STR_LEN("=~"));*/ + break; + case CONFIG_COND_MATCH: + C->key->ptr[pos] = '!'; /* opposite cond */ + /*buffer_copy_string_len(C->op, CONST_STR_LEN("!~"));*/ + break; + default: /* should not happen; CONFIG_COND_ELSE checked further above */ + force_assert(0); + } + + if (NULL == (dc = (data_config *)array_get_element(ctx->all_configs, C->key->ptr))) { + /* re-insert into ctx->all_configs with new C->key */ + array_insert_unique(ctx->all_configs, (data_unset *)C); + C->prev = B; + B->next = C; + } else { + fprintf(stderr, "unreachable else condition\n"); + ctx->ok = 0; + C->free((data_unset *)C); + C = dc; + } + + A = C; + B = NULL; + C = NULL; + } +} + condlines(A) ::= condline(B). { A = B; B = NULL; @@ -429,6 +490,20 @@ condline(A) ::= context LCURLY metalines RCURLY. { } } +cond_else(A) ::= context_else LCURLY metalines RCURLY. { + A = NULL; + if (ctx->ok) { + data_config *cur; + + cur = ctx->current; + configparser_pop(ctx); + + force_assert(cur && ctx->current); + + A = cur; + } +} + context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expression(D). { data_config *dc; buffer *b, *rvalue, *op; @@ -641,20 +716,14 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio } } -context ::= . { +context_else ::= . { if (ctx->ok) { data_config *dc = data_config_init(); buffer_copy_buffer(dc->key, ctx->current->key); buffer_append_string_len(dc->key, CONST_STR_LEN("/")); - buffer_append_string_len(dc->key, CONST_STR_LEN("else")); + buffer_append_string_len(dc->key, CONST_STR_LEN("else_tmp_token")); dc->cond = CONFIG_COND_ELSE; - if (NULL == array_get_element(ctx->all_configs, dc->key->ptr)) { - configparser_push(ctx, dc, 1); - } else { - fprintf(stderr, "repeated else condition\n"); - ctx->ok = 0; - dc->free((data_unset *)dc); - } + configparser_push(ctx, dc, 1); } }