java-topology/defects/postgresql/patch/postgresql-0008-paraminfo-equal-hashops.patch

84 lines
2.7 KiB
Diff

# 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);
}
+ }