]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
expr: catch missing and excess elements in concatenations
authorPatrick McHardy <kaber@trash.net>
Mon, 22 Apr 2013 16:50:44 +0000 (18:50 +0200)
committerPatrick McHardy <kaber@trash.net>
Mon, 22 Apr 2013 16:50:44 +0000 (18:50 +0200)
# nft -nn filter output ip daddr . tcp dport . tcp dport { 192.168.0.1 . ssh }
<cmdline>:1:50-66: Error: datatype mismatch, expected concatenation of (IPv4 address, internet network service, internet network service), expression has type concatenation of (IPv4 address, internet network service)
filter output ip daddr . tcp dport . tcp dport { 192.168.0.1 . ssh }
                                                 ^^^^^^^^^^^^^^^^^

# nft -nn filter output ip daddr . tcp dport . tcp dport { 192.168.0.1 . ssh . ssh . ssh}
<cmdline>:1:76-78: Error: unexpected concat component, expecting concatenation of (IPv4 address, internet network service, internet network service)
filter output ip daddr . tcp dport . tcp dport { 192.168.0.1 . ssh . ssh . ssh}
                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^

Signed-off-by: Patrick McHardy <kaber@trash.net>
src/datatype.c
src/evaluate.c

index 3c17e929f8992e848362234e2335bbeaa8534624..2cb937f559b2927ab5d28426238f899610595179 100644 (file)
@@ -662,20 +662,23 @@ const struct datatype *concat_type_alloc(const struct expr *expr)
 {
        struct datatype *dtype;
        struct expr *i;
-       char desc[256] = "concatenation of ";
-       unsigned int type = 0;
+       char desc[256] = "concatenation of (";
+       unsigned int type = 0, size = 0;
 
        list_for_each_entry(i, &expr->expressions, list) {
-               if (type != 0)
+               if (size != 0)
                        strncat(desc, ", ", sizeof(desc) - strlen(desc) - 1);
                strncat(desc, i->dtype->desc, sizeof(desc) - strlen(desc) - 1);
 
                type <<= 8;
                type  |= i->dtype->type;
+               size++;
        }
+       strncat(desc, ")", sizeof(desc) - strlen(desc) - 1);
 
        dtype           = xzalloc(sizeof(*dtype));
        dtype->type     = type;
+       dtype->size     = size;
        dtype->desc     = xstrdup(desc);
        dtype->parse    = concat_type_parse;
 
index bf169321fc96d855023f1f2084991fbd8e2a4d58..6f90f54f374e8ea2b35693b9cdd3a5382e66ea24 100644 (file)
@@ -585,13 +585,19 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
 {
        const struct datatype *dtype = ctx->ectx.dtype, *tmp;
        unsigned int type = dtype ? dtype->type : 0;
+       int off = dtype ? dtype->size: 0;
        unsigned int flags = EXPR_F_CONSTANT | EXPR_F_SINGLETON;
        struct expr *i, *next;
        unsigned int n;
 
        n = 1;
        list_for_each_entry_safe(i, next, &(*expr)->expressions, list) {
-               tmp = datatype_lookup((type >> 8 * ((*expr)->size - n)) & 0xff);
+               if (dtype && off == 0)
+                       return expr_binary_error(ctx, i, *expr,
+                                                "unexpected concat component, "
+                                                "expecting %s",
+                                                dtype->desc);
+               tmp = datatype_lookup((type >> 8 * --off) & 0xff);
                expr_set_context(&ctx->ectx, tmp, tmp->size);
 
                if (list_member_evaluate(ctx, &i) < 0)
@@ -604,6 +610,12 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr)
        (*expr)->flags |= flags;
        (*expr)->dtype = concat_type_alloc(*expr);
 
+       if (off > 0)
+               return expr_error(ctx, *expr,
+                                 "datatype mismatch, expected %s, "
+                                 "expression has type %s",
+                                 dtype->desc, (*expr)->dtype->desc);
+
        expr_set_context(&ctx->ectx, (*expr)->dtype, (*expr)->len);
 
        return 0;