From 01e6bf680b28286083ed4ccf359c394b7190ceb8 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 9 Oct 2018 12:36:23 +0100 Subject: [PATCH] [Minor] Add more operations sanity check in expressions parser --- src/libutil/expression.c | 128 +++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/src/libutil/expression.c b/src/libutil/expression.c index 65465ceb6..463e3165a 100644 --- a/src/libutil/expression.c +++ b/src/libutil/expression.c @@ -613,78 +613,90 @@ rspamd_parse_expression (const gchar *line, gsize len, case PARSE_ATOM: if (g_ascii_isspace (*p)) { state = SKIP_SPACES; + continue; } else if (rspamd_expr_is_operation_symbol (*p)) { + if (p + 1 < end) { + gchar t = *(p + 1); + + if (g_ascii_isspace (t) || g_ascii_isalnum (t) || + rspamd_expr_is_operation_symbol (t)) { + state = PARSE_OP; + continue; + } + } + else { + state = PARSE_OP; + continue; + } + } + + /* + * First of all, we check some pre-conditions: + * 1) if we have 'and ' or 'or ' or 'not ' strings, they are op + * 2) if we have full numeric string, then we check for + * the following expression: + * ^\d+\s*[><]$ + */ + if ((gulong)(end - p) > sizeof ("and ") && + (g_ascii_strncasecmp (p, "and ", sizeof ("and ") - 1) == 0 || + g_ascii_strncasecmp (p, "not ", sizeof ("not ") - 1) == 0 )) { + state = PARSE_OP; + } + else if ((gulong)(end - p) > sizeof ("or ") && + g_ascii_strncasecmp (p, "or ", sizeof ("or ") - 1) == 0) { state = PARSE_OP; } else { /* - * First of all, we check some pre-conditions: - * 1) if we have 'and ' or 'or ' or 'not ' strings, they are op - * 2) if we have full numeric string, then we check for - * the following expression: - * ^\d+\s*[><]$ + * If we have any comparison operator in the stack, then try + * to parse limit */ - if ((gulong)(end - p) > sizeof ("and ") && - (g_ascii_strncasecmp (p, "and ", sizeof ("and ") - 1) == 0 || - g_ascii_strncasecmp (p, "not ", sizeof ("not ") - 1) == 0 )) { - state = PARSE_OP; - } - else if ((gulong)(end - p) > sizeof ("or ") && - g_ascii_strncasecmp (p, "or ", sizeof ("or ") - 1) == 0) { - state = PARSE_OP; - } - else { - /* - * If we have any comparison operator in the stack, then try - * to parse limit - */ - op = GPOINTER_TO_INT (rspamd_expr_stack_peek (e)); - - if (op >= OP_LT && op <= OP_GE) { - if (rspamd_regexp_search (num_re, - p, - end - p, - NULL, - NULL, - FALSE, - NULL)) { - c = p; - state = PARSE_LIM; - continue; - } + op = GPOINTER_TO_INT (rspamd_expr_stack_peek (e)); + + if (op >= OP_LT && op <= OP_GE) { + if (rspamd_regexp_search (num_re, + p, + end - p, + NULL, + NULL, + FALSE, + NULL)) { + c = p; + state = PARSE_LIM; + continue; } + } - /* Try to parse atom */ - atom = subr->parse (p, end - p, pool, subr_data, err); - if (atom == NULL || atom->len == 0) { - /* We couldn't parse the atom, so go out */ - if (err != NULL && *err == NULL) { - g_set_error (err, - rspamd_expr_quark (), - 500, - "Cannot parse atom: callback function failed" - " to parse '%.*s'", - (int) (end - p), - p); - } - goto err; + /* Try to parse atom */ + atom = subr->parse (p, end - p, pool, subr_data, err); + if (atom == NULL || atom->len == 0) { + /* We couldn't parse the atom, so go out */ + if (err != NULL && *err == NULL) { + g_set_error (err, + rspamd_expr_quark (), + 500, + "Cannot parse atom: callback function failed" + " to parse '%.*s'", + (int) (end - p), + p); } + goto err; + } - if (atom->str == NULL) { - atom->str = p; - } + if (atom->str == NULL) { + atom->str = p; + } - p = p + atom->len; + p = p + atom->len; - /* Push to output */ - elt.type = ELT_ATOM; - elt.p.atom = atom; - g_array_append_val (e->expressions, elt); - rspamd_expr_stack_elt_push (operand_stack, - g_node_new (rspamd_expr_dup_elt (pool, &elt))); + /* Push to output */ + elt.type = ELT_ATOM; + elt.p.atom = atom; + g_array_append_val (e->expressions, elt); + rspamd_expr_stack_elt_push (operand_stack, + g_node_new (rspamd_expr_dup_elt (pool, &elt))); - } } break; case PARSE_LIM: -- 2.39.5