Version: main @ ba5f38815 (still present at 4abee96e7), relwithdebinfo, Linux x86-64.
Repro
MATCH (a) RETURN 1, 2 UNION ALL MATCH (b) RETURN b.id, b.id;
SIGSEGV (exit 139), deterministic. tinysnb-style: MATCH (a:Person) RETURN 1, 2 UNION ALL MATCH (b:Person) RETURN b.age, b.age.
Trigger: a UNION/UNION ALL arm that projects the same scan-derived property expression more than once (e.g. b.id, b.id), in either arm. Does not crash with duplicate literals (1, 1), duplicate node/rel variables (b, b), all-distinct columns, or a single arm without UNION.
Backtrace: garbage shared_ptr deref ← LogicalUnion::requireFlatExpression (logical_union.cpp:48) ← getGroupsPosToFlatten (:13) ← Planner::createUnionPlan.
Root cause (analysis): requireFlatExpression/getGroupsPosToFlatten index each child's getExpressionsInScope() positionally up to the union arity. A duplicated property projection collapses to a single in-scope entry, so the list is shorter than the arity → out-of-bounds vector read → garbage Expression pointer → getGroup(...)->isFlat() dereferences it.
How found: grammar fuzzer; minimized, and the trigger pinned via a controlled truth table (literal-dup and node-var-dup are not triggers; property-dup is).
Version:
main@ba5f38815(still present at4abee96e7),relwithdebinfo, Linux x86-64.Repro
SIGSEGV (exit 139), deterministic. tinysnb-style:
MATCH (a:Person) RETURN 1, 2 UNION ALL MATCH (b:Person) RETURN b.age, b.age.Trigger: a
UNION/UNION ALLarm that projects the same scan-derived property expression more than once (e.g.b.id, b.id), in either arm. Does not crash with duplicate literals (1, 1), duplicate node/rel variables (b, b), all-distinct columns, or a single arm without UNION.Backtrace: garbage
shared_ptrderef ←LogicalUnion::requireFlatExpression(logical_union.cpp:48) ←getGroupsPosToFlatten(:13) ←Planner::createUnionPlan.Root cause (analysis):
requireFlatExpression/getGroupsPosToFlattenindex each child'sgetExpressionsInScope()positionally up to the union arity. A duplicated property projection collapses to a single in-scope entry, so the list is shorter than the arity → out-of-bounds vector read → garbageExpressionpointer →getGroup(...)->isFlat()dereferences it.How found: grammar fuzzer; minimized, and the trigger pinned via a controlled truth table (literal-dup and node-var-dup are not triggers; property-dup is).