diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-11-28 19:04:21 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-11-28 19:41:58 +0100 |
commit | d297735543a8c32b83e40563f01fea33e233b4ef (patch) | |
tree | c1a512da3971f64295d749a06ddf7f2561af1dfe /src/datatype.c | |
parent | 8ff7fed3b0d866268322d27511ddc73fbd8c77c8 (diff) |
datatype: fix crash when using basetype instead of symbolic constants
The following example:
# nft add rule filter input ct state 8 accept
Segmentation fault
leads to a crash because we have the following datatype relation:
ct_state -> bitmask -> integer
The bitmask, which is an intermediate basetype, has no parse()
function, this leads to a crash in symbolic_constant_parse().
Patrick suggested to walk down the chain until we find a parser
function.
Reported-by: leroy christophe <christophe.leroy@c-s.fr>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/datatype.c')
-rw-r--r-- | src/datatype.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/src/datatype.c b/src/datatype.c index 5f976aa3..7c9c3d48 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -125,21 +125,28 @@ struct error_record *symbolic_constant_parse(const struct expr *sym, break; } - dtype = sym->dtype; - if (s->identifier == NULL) { - *res = NULL; - erec = sym->dtype->basetype->parse(sym, res); - if (erec != NULL) - return erec; - if (*res) - return NULL; + if (s->identifier != NULL) + goto out; - return error(&sym->location, "Could not parse %s", dtype->desc); - } + dtype = sym->dtype; + *res = NULL; + do { + if (dtype->basetype->parse) { + erec = dtype->basetype->parse(sym, res); + if (erec != NULL) + return erec; + if (*res) + return NULL; + goto out; + } + } while ((dtype = dtype->basetype)); - *res = constant_expr_alloc(&sym->location, dtype, - dtype->byteorder, dtype->size, - constant_data_ptr(s->value, dtype->size)); + return error(&sym->location, "Could not parse %s", sym->dtype->desc); +out: + *res = constant_expr_alloc(&sym->location, sym->dtype, + sym->dtype->byteorder, sym->dtype->size, + constant_data_ptr(s->value, + sym->dtype->size)); return NULL; } |