]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Make stack depth check work with asan's use-after-return
authorAndres Freund <andres@anarazel.de>
Thu, 28 May 2026 15:34:11 +0000 (11:34 -0400)
committerAndres Freund <andres@anarazel.de>
Thu, 28 May 2026 15:43:29 +0000 (11:43 -0400)
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.

We started using __builtin_frame_address() with de447bb8e6fb, however as of
that commit we just used it for the stack base address, not for the value to
compare to the base address.  Now we use it for both.

When building without __builtin_frame_address() support, we continue to use
stack variables for the stack depth determination.

Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/2kk4z4odvuyrg7qlwjd7ft4eron4cle4btb33v4qatgsdkayir@gj6e62rgsel4
Backpatch-through: 14

.cirrus.tasks.yml
src/backend/utils/misc/stack_depth.c

index a22cef063f337ababbaec245413d4d254a6bf4c4..8683d1ae9c70648ee86e6b3fe7a724827438d75d 100644 (file)
@@ -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
index 61a07cf824e9f23a888bd6228965310b2a2ec506..914a4393bf3f6039a95e2e4763550a2385c75161 100644 (file)
@@ -53,7 +53,8 @@ set_stack_base(void)
        /*
         * Set up reference point for stack depth checking.  On recent gcc we use
         * __builtin_frame_address() to avoid a warning about storing a local
-        * variable's address in a long-lived variable.
+        * variable's address in a long-lived variable.  This is also important
+        * with address sanitizer, see comment in stack_is_too_deep().
         */
 #ifdef HAVE__BUILTIN_FRAME_ADDRESS
        stack_base_ptr = __builtin_frame_address(0);
@@ -108,13 +109,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
+        * Compute distance from reference point to my stack frame.
         */
-       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