summaryrefslogtreecommitdiff
path: root/src/configparser.y
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2016-10-09 09:20:37 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2016-10-09 09:20:37 -0400
commitce24523b59ed97a42b2e446036b70f490400688f (patch)
tree98a1bbf27cbd3213d06fc552c4952c354c85ce37 /src/configparser.y
parent79fb75709bf48ad3fc1de381f36512068ccca52d (diff)
downloadlighttpd-git-ce24523b59ed97a42b2e446036b70f490400688f.tar.gz
[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
Diffstat (limited to 'src/configparser.y')
-rw-r--r--src/configparser.y87
1 files 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);
}
}