From 836bc0f6b46c08fc66970a90c5fedbde300fb815 Mon Sep 17 00:00:00 2001 From: zhangwenchao <656540940@qq.com> Date: Mon, 22 Jun 2026 18:51:34 +0800 Subject: [PATCH] Fix use-after-free in CXformSplitWindowFunc CXformSplitWindowFunc::Transform() builds a local and a global CLogicalSequenceProject, and each constructor takes ownership of one reference to the window's distribution spec (pds), order specs (pdrgpos) and frames (pdrgpwf). Only a single AddRef() was issued for each object, so once both SequenceProjects and the original are released the reference count underflows and the objects are freed while still in use. The dangling memory later surfaces as a corrupt (unaligned) scalar DXL node while translating a table scan filter, crashing the coordinator with SIGSEGV at CTranslatorDXLToScalar.cpp:111 during DXL-to-PlStmt translation. This reproduces on window-function queries (e.g. TPC-DS query 44) when optimizer_force_split_window_function is on; the transform is only enabled under that GUC, which is why the crash disappears when it is off. Add the missing AddRef() for pds, pdrgpos and pdrgpwf before building the global SequenceProject, and for the Select operator and its scalar comparison before reusing them in the global Select, so every owner holds its own reference. --- .../libgpopt/src/xforms/CXformSplitWindowFunc.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/backend/gporca/libgpopt/src/xforms/CXformSplitWindowFunc.cpp b/src/backend/gporca/libgpopt/src/xforms/CXformSplitWindowFunc.cpp index 92a310101bc..be1c5efa278 100644 --- a/src/backend/gporca/libgpopt/src/xforms/CXformSplitWindowFunc.cpp +++ b/src/backend/gporca/libgpopt/src/xforms/CXformSplitWindowFunc.cpp @@ -375,6 +375,16 @@ CXformSplitWindowFunc::Transform(CXformContext *pxfctxt, CXformResult *pxfres, CExpression *pexprLocalSelect = GPOS_NEW(mp) CExpression(mp, pSelectCopy, pexprLocal, pexprScalarCmp); + // the global SequenceProject below takes ownership of one reference each to + // pds, pdrgpos and pdrgpwf, just like the local SequenceProject above. Only + // a single AddRef() was issued for each of them, so add the matching + // references here; otherwise the reference count underflows, these objects + // are freed while still in use, and the dangling memory later crashes the + // DXL-to-PlStmt translation (use-after-free) + pds->AddRef(); + pdrgpos->AddRef(); + pdrgpwf->AddRef(); + CExpression *pexprGlobal = GPOS_NEW(mp) CExpression(mp, GPOS_NEW(mp) CLogicalSequenceProject( @@ -382,6 +392,9 @@ CXformSplitWindowFunc::Transform(CXformContext *pxfctxt, CXformResult *pxfres, pdrgpos, pdrgpwf), pexprLocalSelect, pexprProjectListGlobal); + pexpr->Pop()->AddRef(); + pexprScalarCmp->AddRef(); + CExpression *pexprGlobalSelect = GPOS_NEW(mp) CExpression(mp, pexpr->Pop(), pexprGlobal, pexprScalarCmp);