From 2cbe2650f80f062928dbb0e8bc60fc5d602d24af Mon Sep 17 00:00:00 2001
From: test <test>
Date: Sat, 2 May 2026 23:09:00 +0200
Subject: [PATCH] valgrind: add NOACCESS sentinels for dynamic shmem

When build with USE_VALGRIND, add a couple NOACCESS bytes after each
entry allocated from the segment.

Unfortunately, these markings don't seem to be shared between processes,
so it applies only for the process that sets it up (i.e. the parallel
leader), and not the workers. Even with this limitation it seems useful,
as the leader may participate in the processing. We also have
debug_parallel_query=regress, running everything in a single process.
---
 src/backend/storage/ipc/shm_toc.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/src/backend/storage/ipc/shm_toc.c b/src/backend/storage/ipc/shm_toc.c
index 2f9fbb0a519..0c17e1adf85 100644
--- a/src/backend/storage/ipc/shm_toc.c
+++ b/src/backend/storage/ipc/shm_toc.c
@@ -16,6 +16,7 @@
 #include "port/atomics.h"
 #include "storage/shm_toc.h"
 #include "storage/spin.h"
+#include "utils/memdebug.h"
 
 typedef struct shm_toc_entry
 {
@@ -74,6 +75,13 @@ shm_toc_attach(uint64 magic, void *address)
 	return toc;
 }
 
+/* with valgrind, we want to add a couple NOACCESS bytes */
+#ifdef USE_VALGRIND
+#define NUM_NOACCESS_BYTES 32
+#else
+#define NUM_NOACCESS_BYTES 0
+#endif
+
 /*
  * Allocate shared memory from a segment managed by a table of contents.
  *
@@ -119,9 +127,19 @@ shm_toc_allocate(shm_toc *toc, Size nbytes)
 	}
 	vtoc->toc_allocated_bytes += nbytes;
 
+#ifdef USE_VALGRIND
+	vtoc->toc_allocated_bytes += NUM_NOACCESS_BYTES;
+#endif
+
 	SpinLockRelease(&toc->toc_mutex);
 
-	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes);
+#ifdef USE_VALGRIND
+	/* make the bytes at the end no-access */
+	VALGRIND_MAKE_MEM_NOACCESS(((char *) toc) + (total_bytes - allocated_bytes - NUM_NOACCESS_BYTES),
+							   NUM_NOACCESS_BYTES);
+#endif
+
+	return ((char *) toc) + (total_bytes - allocated_bytes - nbytes - NUM_NOACCESS_BYTES);
 }
 
 /*
@@ -275,5 +293,8 @@ shm_toc_estimate(shm_toc_estimator *e)
 	sz = add_size(sz, mul_size(e->number_of_keys, sizeof(shm_toc_entry)));
 	sz = add_size(sz, e->space_for_chunks);
 
+	/* add space for ENOACCESS bytes, NUM_NOACCESS_BYTES per key */
+	sz = add_size(sz, mul_size(e->number_of_keys, NUM_NOACCESS_BYTES));
+
 	return BUFFERALIGN(sz);
 }
-- 
2.54.0

