From 093e2a5a070aca5bf8f0d0551a48b2c55b96631c Mon Sep 17 00:00:00 2001 From: Henson Choi Date: Tue, 23 Jun 2026 15:13:27 +0900 Subject: [PATCH v50 28/29] Free RPR NFA states with pfree() under USE_VALGRIND execRPR.c recycles freed RPRNFAState nodes through a free list (nfa_state_free populates it; nfa_state_make reuses from it). That recycling hides use-after-free bugs: a stale reference to a freed state keeps pointing at a live, reused node, so Valgrind never sees a problem. Under USE_VALGRIND, hand the node back to the allocator with pfree() instead of pushing it onto the free list, so memcheck can catch any stray access to a freed state. nfa_state_free is the only place that fills the free list, so this single guard suffices; non-Valgrind builds keep the recycling path unchanged. --- src/backend/executor/execRPR.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backend/executor/execRPR.c b/src/backend/executor/execRPR.c index e5e30d79f01..a85ab563abb 100644 --- a/src/backend/executor/execRPR.c +++ b/src/backend/executor/execRPR.c @@ -243,8 +243,13 @@ static void nfa_state_free(WindowAggState *winstate, RPRNFAState *state) { winstate->nfaStatesActive--; +#ifdef USE_VALGRIND + /* real free so Valgrind catches use-after-free instead of recycling */ + pfree(state); +#else state->next = winstate->nfaStateFree; winstate->nfaStateFree = state; +#endif } /* -- 2.50.1 (Apple Git-155)