0001-pg_stat_statements-Fix-potential-use-after-free-of-P.patch

text/plain

Filename: 0001-pg_stat_statements-Fix-potential-use-after-free-of-P.patch
Type: text/plain
Part: 0
Message: Re: Fix unsafe PlannedStmt access in pg_stat_statements

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch 0001
Subject: pg_stat_statements: Fix potential use-after-free of PlannedStmt
File+
contrib/pg_stat_statements/expected/plancache.out 38 0
contrib/pg_stat_statements/pg_stat_statements.c 2 1
contrib/pg_stat_statements/sql/plancache.sql 19 0
From 19281d8708facd17cd65a9ab07dd7b775496a5c9 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Tue, 12 May 2026 12:24:52 +0900
Subject: [PATCH] pg_stat_statements: Fix potential use-after-free of
 PlannedStmt

Blahblahblah.

Author: Chao Li
Co-authored-by: Michael Paquier
Discussion: https://postgr.es/m/
---
 .../pg_stat_statements/expected/plancache.out | 38 +++++++++++++++++++
 .../pg_stat_statements/pg_stat_statements.c   |  3 +-
 contrib/pg_stat_statements/sql/plancache.sql  | 19 ++++++++++
 3 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/contrib/pg_stat_statements/expected/plancache.out b/contrib/pg_stat_statements/expected/plancache.out
index 32bf913b2861..d0796d5693c0 100644
--- a/contrib/pg_stat_statements/expected/plancache.out
+++ b/contrib/pg_stat_statements/expected/plancache.out
@@ -216,6 +216,44 @@ SELECT calls, generic_plan_calls, custom_plan_calls, toplevel, query FROM pg_sta
 
 RESET pg_stat_statements.track;
 --
+-- Procedure with internal ROLLBACK and the extended query protocol.
+-- The PlannedStmt used in pgss_ProcessUtility() is freed by the internal
+-- ROLLBACK.
+--
+CREATE OR REPLACE PROCEDURE rollback_proc(a INOUT int) AS $$
+BEGIN
+  ROLLBACK;
+END;
+$$ LANGUAGE plpgsql;
+SELECT pg_stat_statements_reset() IS NOT NULL AS t;
+ t 
+---
+ t
+(1 row)
+
+CALL rollback_proc($1) \parse stmt_rollback
+\bind_named stmt_rollback 1 \g
+ a 
+---
+ 1
+(1 row)
+
+\bind_named stmt_rollback 2 \g
+ a 
+---
+ 2
+(1 row)
+
+SELECT calls, query FROM pg_stat_statements
+  WHERE query LIKE '%rollback_proc%'
+  ORDER BY query COLLATE "C";
+ calls |         query          
+-------+------------------------
+     2 | CALL rollback_proc($1)
+(1 row)
+
+DROP PROCEDURE rollback_proc;
+--
 -- Cleanup
 --
 DROP FUNCTION select_one_func(int);
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 95a5411a39d9..a2d3ab770cc6 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -1099,6 +1099,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
 	int64		saved_queryId = pstmt->queryId;
 	int			saved_stmt_location = pstmt->stmt_location;
 	int			saved_stmt_len = pstmt->stmt_len;
+	PlannedStmtOrigin saved_planOrigin = pstmt->planOrigin;
 	bool		enabled = pgss_track_utility && pgss_enabled(nesting_level);
 
 	/*
@@ -1210,7 +1211,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
 				   NULL,
 				   0,
 				   0,
-				   pstmt->planOrigin);
+				   saved_planOrigin);
 	}
 	else
 	{
diff --git a/contrib/pg_stat_statements/sql/plancache.sql b/contrib/pg_stat_statements/sql/plancache.sql
index 160ced7add36..948d3e985180 100644
--- a/contrib/pg_stat_statements/sql/plancache.sql
+++ b/contrib/pg_stat_statements/sql/plancache.sql
@@ -87,6 +87,25 @@ SELECT calls, generic_plan_calls, custom_plan_calls, toplevel, query FROM pg_sta
 
 RESET pg_stat_statements.track;
 
+--
+-- Procedure with internal ROLLBACK and the extended query protocol.
+-- The PlannedStmt used in pgss_ProcessUtility() is freed by the internal
+-- ROLLBACK.
+--
+CREATE OR REPLACE PROCEDURE rollback_proc(a INOUT int) AS $$
+BEGIN
+  ROLLBACK;
+END;
+$$ LANGUAGE plpgsql;
+SELECT pg_stat_statements_reset() IS NOT NULL AS t;
+CALL rollback_proc($1) \parse stmt_rollback
+\bind_named stmt_rollback 1 \g
+\bind_named stmt_rollback 2 \g
+SELECT calls, query FROM pg_stat_statements
+  WHERE query LIKE '%rollback_proc%'
+  ORDER BY query COLLATE "C";
+DROP PROCEDURE rollback_proc;
+
 --
 -- Cleanup
 --
-- 
2.54.0