From efeda879b4de167a54b49b143998d958f7473887 Mon Sep 17 00:00:00 2001
From: Julien Tachoires <julien@tachoires.me>
Date: Tue, 2 Dec 2025 10:38:45 +0100
Subject: [PATCH 1/7] Release buffer lock before scan key evaluation

heapgettup() hold a buffer lock to examine tuple visibility.
When the tuple is visible, the buffer lock can be released before
calling HeapKeyTest() in order to avoid abritrary code execution
due to scan key evaluation while the buffer lock is held. Holding
the buffer pin is enough to access tuple's data.
---
 src/backend/access/heap/heapam.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 4d382a04338..1d9f9efa4fd 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -975,13 +975,27 @@ continue_page:
 			if (!visible)
 				continue;
 
+			/*
+			 * If tuple visibility is statisfied, then we can release the
+			 * buffer lock before evaluating the scan keys in order to avoid
+			 * abritrary code execution while we hold the lock.
+			 */
+			LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
+
 			/* skip any tuples that don't match the scan key */
 			if (key != NULL &&
 				!HeapKeyTest(tuple, RelationGetDescr(scan->rs_base.rs_rd),
 							 nkeys, key))
+			{
+				/*
+				 * When the tuple is visible but does not satisfy any scan
+				 * key, then we have to re-acquire the buffer lock to examine
+				 * next tuple's visibility.
+				 */
+				LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
 				continue;
+			}
 
-			LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
 			scan->rs_coffset = lineoff;
 			return;
 		}
-- 
2.39.5

