From 47ae322d41923becb870b289240d85edd1e938ee 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 2669f2c3017..e8f0e74db5d 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -5522,35 +5522,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; @@ -5577,7 +5583,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;