From 6f96bb5d11e67fb0cfe3c2f9468233c0019a57e4 Mon Sep 17 00:00:00 2001 From: Jianghua Yang Date: Sat, 9 Aug 2025 05:28:01 +0800 Subject: [PATCH] Prevent use after free in flatten_join_alias_var_optimizer function This patch prevents several use after free bugs present in flatten_join_alias_var_optimizer. Specifically, the function uses flatten_join_alias_vars function multiple times, and assumes that the original node can be freed immediately after. This is not always the case since under some circumstances flatten_join_alias_vars does not modify its input and simply passes it through without copying. This patch adds conditions to check if the original node can safely be freed, preventing use after free. --- src/backend/optimizer/util/clauses.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 1fd03a05e87..769ff190324 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -5528,35 +5528,41 @@ flatten_join_alias_var_optimizer(Query *query, int queryLevel) if (NIL != targetList) { queryNew->targetList = (List *) flatten_join_alias_vars(queryNew, (Node *) targetList); - list_free(targetList); + /* We can free the old list only if it was replaced */ + if (targetList != queryNew->targetList) + list_free(targetList); } List * returningList = queryNew->returningList; if (NIL != returningList) { queryNew->returningList = (List *) flatten_join_alias_vars(queryNew, (Node *) returningList); - list_free(returningList); + if (returningList != queryNew->returningList) + list_free(returningList); } Node *havingQual = queryNew->havingQual; if (NULL != havingQual) { queryNew->havingQual = flatten_join_alias_vars(queryNew, havingQual); - pfree(havingQual); + if (havingQual != queryNew->havingQual) + pfree(havingQual); } List *scatterClause = queryNew->scatterClause; if (NIL != scatterClause) { queryNew->scatterClause = (List *) flatten_join_alias_vars(queryNew, (Node *) scatterClause); - list_free(scatterClause); + if (scatterClause != queryNew->scatterClause) + list_free(scatterClause); } Node *limitOffset = queryNew->limitOffset; if (NULL != limitOffset) { queryNew->limitOffset = flatten_join_alias_vars(queryNew, limitOffset); - pfree(limitOffset); + if (limitOffset != queryNew->limitOffset) + pfree(limitOffset); } List *windowClause = queryNew->windowClause; @@ -5583,7 +5589,8 @@ flatten_join_alias_var_optimizer(Query *query, int queryLevel) if (NULL != limitCount) { queryNew->limitCount = flatten_join_alias_vars(queryNew, limitCount); - pfree(limitCount); + if (limitCount != queryNew->limitCount) + pfree(limitCount); } return queryNew;