Subject: [PATCH v2 1/4] Make stack depth check work with asan's use-after-return

From: Andres Freund <[email-masked]>
Date: Sat, 7 Feb 2026 14:04:06 -0500

With address sanitizer's stack-use-after-return check, stack variables are
moved to heap allocations, to allow to detect references to the memory at a
later time. That broke our stack-depth check, which is why we had to disable
detect_stack_use_after_return in CI. Luckily __builtin_frame_address() works
correctly, even under asan, so use that.

Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/utils/misc/stack_depth.c | 17 ++++++++++++++++-
 .cirrus.tasks.yml                    |  2 +-
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/backend/utils/misc/stack_depth.c b/src/backend/utils/misc/stack_depth.c
index 61a07cf824e..9955e28c176 100644
--- a/src/backend/utils/misc/stack_depth.c
+++ b/src/backend/utils/misc/stack_depth.c
@@ -108,13 +108,28 @@ check_stack_depth(void)
 bool
 stack_is_too_deep(void)
 {
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
 	char		stack_top_loc;
+#endif
 	ssize_t		stack_depth;
+	char	   *stack_address;
+
+	/*
+	 * With address sanitizer's stack-use-after-return check, stack variables
+	 * are moved to heap allocations, to allow to detect references to the
+	 * memory at a later time. That would break our stack-depth check. Luckily
+	 * __builtin_frame_address() works correctly, even under asan.
+	 */
+#ifndef HAVE__BUILTIN_FRAME_ADDRESS
+	stack_address = &stack_top_loc;
+#else
+	stack_address = (char *) __builtin_frame_address(0);
+#endif
 
 	/*
 	 * Compute distance from reference point to my local variables
 	 */
-	stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
+	stack_depth = (ssize_t) (stack_base_ptr - stack_address);
 
 	/*
 	 * Take abs value, since stacks grow up on some machines, down on others
diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index a22cef063f3..8683d1ae9c7 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -447,7 +447,7 @@ task:
     # print_stacktraces=1,verbosity=2, duh
     # detect_leaks=0: too many uninteresting leak errors in short-lived binaries
     UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2
-    ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0
+    ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0
 
     # SANITIZER_FLAGS is set in the tasks below
     CFLAGS: -Og -ggdb -fno-sanitize-recover=all $SANITIZER_FLAGS
-- 
2.53.0.1.gb2826b52eb

--7e2sypi5gxvkgog6--