[PATCH 1/7] Release buffer lock before scan key evaluation
Julien Tachoires <julien@tachoires.me>
From: Julien Tachoires <julien@tachoires.me>
To:
Date: 2025-12-02T09:38:45Z
Lists: pgsql-hackers
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
--lqhr7owlpsibhw3z
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
filename="v4-0002-Pass-the-number-of-ScanKeys-to-scan_rescan.patch"