# UNDF: UNDF-2026-000000220 diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index abcdef..123456 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -481,6 +481,13 @@ paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info, { List *lateral_vars; ListCell *lc; + /* + * CWE-407 fix (postgresql-0008, joinpath.c): + * Track seen Var exprs via a Bitmapset (O(1) per check) instead of + * list_member(*param_exprs, ...) which is O(|param_exprs|) and makes + * the full deduplication loop O(N²). Non-Var nodes fall back to a + * kept list and structural equal() — they are rare in practice. + */ + Bitmapset *seen_bms = NULL; + List *seen_nonvar = NIL; *param_exprs = NIL; *operators = NIL; @@ -534,9 +541,27 @@ paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info, * 'expr' may already exist as a parameter from a previous item in * ppi_clauses. No need to include it again, however we'd better * ensure we do switch into binary mode if required. See below. */ - if (!list_member(*param_exprs, expr)) + { + bool already_seen; + + if (IsA(expr, Var)) + { + Var *v = (Var *) expr; + int key = v->varno * 3200 + v->varattno + 1600; + + already_seen = bms_is_member(key, seen_bms); + if (!already_seen) + seen_bms = bms_add_member(seen_bms, key); + } + else + { + already_seen = list_member(seen_nonvar, expr); + if (!already_seen) + seen_nonvar = lappend(seen_nonvar, expr); + } + if (!already_seen) { *operators = lappend_oid(*operators, hasheqoperator); *param_exprs = lappend(*param_exprs, expr); } + } /* * When the join operator is not hashable then it's possible that @@ -584,9 +599,24 @@ paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info, * 'expr' may already exist as a parameter from the ppi_clauses. No * need to include it again, however we'd better ensure we do switch * into binary mode. */ - if (!list_member(*param_exprs, expr)) + { + bool already_seen; + + if (IsA(expr, Var)) + { + Var *v = (Var *) expr; + int key = v->varno * 3200 + v->varattno + 1600; + + already_seen = bms_is_member(key, seen_bms); + if (!already_seen) + seen_bms = bms_add_member(seen_bms, key); + } + else + { + already_seen = list_member(seen_nonvar, expr); + if (!already_seen) + seen_nonvar = lappend(seen_nonvar, expr); + } + if (!already_seen) { *operators = lappend_oid(*operators, typentry->eq_opr); *param_exprs = lappend(*param_exprs, expr); } + }