[PATCH v2 1/4] Make stack depth check work with asan's use-after-return
Andres Freund <andres@anarazel.de>
From: Andres Freund <andres@anarazel.de>
To:
Date: 2026-02-07T19:04:06Z
Lists: pgsql-hackers
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--