This is an automated email from the ASF dual-hosted git repository.

yjhjstz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 224f15320c74f387073edc453af83a030d7caafe
Author: Jianghua Yang <[email protected]>
AuthorDate: Sat Mar 14 03:50:51 2026 +0800

    ORCA: Fix use-after-free in flatten_join_alias_var_optimizer
    
    Guard pfree/list_free calls with pointer-equality checks to avoid
    freeing live nodes when flatten_join_alias_vars returns the same
    pointer unchanged (e.g., outer-reference Vars with varlevelsup > 0).
    
    The unconditional pfree(havingQual) freed the Var node, whose memory
    was later reused by palloc for a T_List. copyObjectImpl then copied
    the wrong node type into havingQual, causing ORCA to encounter an
    unexpected RangeTblEntry and fall back to the Postgres planner.
    
    Applies the same guard pattern to all six fields: targetList,
    returningList, havingQual, scatterClause, limitOffset, limitCount.
    
    Reported-in: https://github.com/apache/cloudberry/issues/1618
---
 src/backend/optimizer/util/clauses.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/src/backend/optimizer/util/clauses.c 
b/src/backend/optimizer/util/clauses.c
index 2669f2c3017..9085f3876a4 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -5522,35 +5522,40 @@ 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);
+               if (targetList != queryNew->targetList)
+                       list_free(targetList);
        }
 
-       List * returningList = queryNew->returningList;
+       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 +5582,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;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to