Thread

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

    Andres Freund <andres@anarazel.de> — 2026-02-07T19:04:06Z

    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--