From: Florian Westphal Date: Mon, 31 Mar 2025 12:27:47 +0000 (+0200) Subject: json: fix error propagation when parsing binop lhs/rhs X-Git-Tag: v1.1.2~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1b6470ab1c4eff46986e65db1b69278f13c26666;p=thirdparty%2Fnftables.git json: fix error propagation when parsing binop lhs/rhs Malformed input returns NULL when decoding left/right side of binop. This causes a NULL dereference in expr_evaluate_binop; left/right must point to a valid expression. Fix this in the parser, else would have to sprinkle NULL checks all over the evaluation code. After fix, loading the bogon yields: internal:0:0-0: Error: Malformed object (too many properties): '{}'. internal:0:0-0: Error: could not decode binop rhs, '<<'. internal:0:0-0: Error: Invalid mangle statement value internal:0:0-0: Error: Parsing expr array at index 1 failed. internal:0:0-0: Error: Parsing command array at index 3 failed. Fixes: 0ac39384fd9e ("json: Accept more than two operands in binary expressions") Signed-off-by: Florian Westphal Reviewed-by: Pablo Neira Ayuso --- diff --git a/src/parser_json.c b/src/parser_json.c index 04d76274..9d5ec227 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -1210,11 +1210,25 @@ static struct expr *json_parse_binop_expr(struct json_ctx *ctx, if (json_array_size(root) > 2) { left = json_parse_primary_expr(ctx, json_array_get(root, 0)); + if (!left) { + json_error(ctx, "Failed to parse LHS of binop expression."); + return NULL; + } right = json_parse_primary_expr(ctx, json_array_get(root, 1)); + if (!right) { + json_error(ctx, "Failed to parse RHS of binop expression."); + expr_free(left); + return NULL; + } left = binop_expr_alloc(int_loc, thisop, left, right); for (i = 2; i < json_array_size(root); i++) { jright = json_array_get(root, i); right = json_parse_primary_expr(ctx, jright); + if (!right) { + json_error(ctx, "Failed to parse RHS of binop expression."); + expr_free(left); + return NULL; + } left = binop_expr_alloc(int_loc, thisop, left, right); } return left; diff --git a/tests/shell/testcases/bogons/nft-j-f/binop_rhs_decode_error_crash b/tests/shell/testcases/bogons/nft-j-f/binop_rhs_decode_error_crash new file mode 100644 index 00000000..8b5b7290 --- /dev/null +++ b/tests/shell/testcases/bogons/nft-j-f/binop_rhs_decode_error_crash @@ -0,0 +1,76 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "t", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c", + "handle": 0, + "type": "filter", + "hook": "output", + "prio": 0, + "policy": "accept" + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "meta": { + "key": "oif" + } + }, + "right": "lo" + } + }, + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": { + "<<": [ + { + "|": [ + { + "meta": { + "key": "mark" + } + }, + 16 + ] + }, + { }, + 8 + ] + } + } + } + ] + } + } + ] +}