From 5afa5a164ff1c066af1ec56d875b91562882bd50 Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Wed, 11 May 2016 13:30:02 +0200 Subject: evaluate: check for NULL datatype in rhs in lookup expr If we are evaluating an EXPR_SET_REF, check if right->dtype is not NULL. We can hit SEGFAULT if for whatever reason the referenced object does not exist. Using this testfile (note the invalid set syntax): % cat test.nft flush ruleset add table t add chain t c add set t s {type ipv4_addr\;} add rule t c ip saddr @s Without this patch: % nft -f test.nft Segmentation fault With this patch: % nft -f test.nft t.nft:4:28-28: Error: syntax error, unexpected junk, expecting newline or semicolon add set t s {type ipv4_addr\;} ^ t.nft:4:13-29: Error: set definition does not specify key data type add set t s {type ipv4_addr\;} ^^^^^^^^^^^^^^^^^ t.nft:5:23-24: Error: the referenced set does not exist add rule t c ip saddr @s ~~~~~~~~ ^^ Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- src/evaluate.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/evaluate.c b/src/evaluate.c index fcd4ecda..3afb8ead 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -1381,16 +1381,32 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr) switch (rel->op) { case OP_LOOKUP: - /* A literal set expression implicitly declares the set */ - if (right->ops->type == EXPR_SET) + switch (right->ops->type) { + case EXPR_SET: + /* A literal set expression implicitly declares + * the set + */ right = rel->right = - implicit_set_declaration(ctx, left->dtype, left->len, right); - else if (!datatype_equal(left->dtype, right->dtype)) - return expr_binary_error(ctx->msgs, right, left, - "datatype mismatch, expected %s, " - "set has type %s", - left->dtype->desc, - right->dtype->desc); + implicit_set_declaration(ctx, left->dtype, + left->len, right); + break; + case EXPR_SET_REF: + if (right->dtype == NULL) + return expr_binary_error(ctx->msgs, right, + left, "the referenced" + " set does not " + "exist"); + if (!datatype_equal(left->dtype, right->dtype)) + return expr_binary_error(ctx->msgs, right, + left, "datatype " + "mismatch, expected " + "%s, set has type %s", + left->dtype->desc, + right->dtype->desc); + break; + default: + BUG("Unknown expression %s\n", right->ops->name); + } /* Data for range lookups needs to be in big endian order */ if (right->set->flags & SET_F_INTERVAL && -- cgit v1.2.3