]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
expression: fix constant expression allocation on big endian
authorArturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
Sat, 12 Apr 2014 08:40:08 +0000 (10:40 +0200)
committerPatrick McHardy <kaber@trash.net>
Sat, 12 Apr 2014 08:40:08 +0000 (10:40 +0200)
When allocating a constant expression, a pointer to the data is passed
to the allocation function. When the variable used to store the data
is larger than the size of the data type, this fails on big endian since
the most significant bytes (being zero) come first.

Add a helper function to calculate the proper address for the cases
where this is needed.

This currently affects symbolic tables for values < u64 and payload
dependency generation for protocol values < u32.

Signed-off-by: Patrick McHardy <kaber@trash.net>
include/utils.h
src/datatype.c
src/payload.c

index 88ee0c9ca91a4e32ee1d3f740e01497a31001e72..cc5948c18d5e0fbe18b3bd1f5f5adc32cfb14342 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef NFTABLES_UTILS_H
 #define NFTABLES_UTILS_H
 
+#include <asm/byteorder.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdarg.h>
        typeof( ((type *)0)->member ) *__mptr = (ptr);          \
        (type *)( (void *)__mptr - offsetof(type,member) );})
 
+/**
+ * Return a pointer to a constant variable of a size smaller than the variable.
+ */
+#ifdef __LITTLE_ENDIAN_BITFIELD
+#define constant_data_ptr(val, len) \
+       ((void *)&(val))
+#elif defined(__BIG_ENDIAN_BITFIELD)
+#define constant_data_ptr(val, len) \
+       ((void *)&(val) + sizeof(val) - (len) / BITS_PER_BYTE)
+#else
+#error "byteorder undefined"
+#endif
+
 #define field_sizeof(t, f)     (sizeof(((t *)NULL)->f))
 #define array_size(arr)                (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 #define div_round_up(n, d)     (((n) + (d) - 1) / (d))
index ac42faa8a002cdbe1565d5e21b7672358c6c5f0d..331f235a7d122746e274d0678ade7fbe22dffd01 100644 (file)
@@ -124,7 +124,7 @@ struct error_record *symbolic_constant_parse(const struct expr *sym,
 
        *res = constant_expr_alloc(&sym->location, dtype,
                                   dtype->byteorder, dtype->size,
-                                  &s->value);
+                                  constant_data_ptr(s->value, dtype->size));
        return NULL;
 }
 
index 427080c0c1e9dd83249eccba881dc3b87549436e..a1785a59bf59c4cfa07a25219b3a92d1912bc5a2 100644 (file)
@@ -209,7 +209,8 @@ int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
 
        right = constant_expr_alloc(&expr->location, tmpl->dtype,
                                    BYTEORDER_HOST_ENDIAN,
-                                   tmpl->len, &protocol);
+                                   tmpl->len,
+                                   constant_data_ptr(protocol, tmpl->len));
 
        dep = relational_expr_alloc(&expr->location, OP_EQ, left, right);
        left->ops->pctx_update(&ctx->pctx, dep);