Skip to content

su_tagarg: fall back to the va_list copy path under AddressSanitizer#332

Open
garacil wants to merge 1 commit into
freeswitch:masterfrom
garacil:fix-210-tagstack-asan
Open

su_tagarg: fall back to the va_list copy path under AddressSanitizer#332
garacil wants to merge 1 commit into
freeswitch:masterfrom
garacil:fix-210-tagstack-asan

Conversation

@garacil

@garacil garacil commented Jul 5, 2026

Copy link
Copy Markdown

The SU_HAVE_TAGSTACK fast path reads the variable arguments directly off the caller's stack — ta_start() stores tl[1] = TAG_NEXT(&(v) + 1). When the resulting tag list is walked (e.g. tl_len() / tl_adup() following t_next()t_next_next()), that raw stack pointer is dereferenced below the ta stack object, which AddressSanitizer correctly reports as a stack-buffer-underflow (the trace in this issue is via nua_create()).

The fix does not touch TAG_TYPE_OF()/tl_len(). It gates the stack fast path on a new SU_TAGARG_USE_TAGSTACK = SU_HAVE_TAGSTACK && !AddressSanitizer (GCC __SANITIZE_ADDRESS__ / clang __has_feature(address_sanitizer)) and uses it for both ta_start() and ta_end(). Under ASan the existing portable va_list copy path (tl_vlist / tl_vfree) is taken instead, which never walks below the frame.

Normal builds are unchanged (SU_TAGARG_USE_TAGSTACK == SU_HAVE_TAGSTACK), and the ta_list layout (tagi_t tl[2]) is identical for both paths, so this is ABI-neutral. Verified: full build is warning-free, and a standalone preprocessor check prints USE_TAGSTACK=1 for a normal GCC build and USE_TAGSTACK=0 under -fsanitize=address.

Fixes #210.

The SU_HAVE_TAGSTACK fast path reads the variable arguments directly off the
caller's stack (ta_start() stores tl[1] = TAG_NEXT(&(v) + 1)). When the
resulting tag list is walked - e.g. tl_len() / tl_adup() following t_next() ->
t_next_next() - the raw stack pointer is dereferenced below the ta stack
object, which AddressSanitizer correctly reports as a stack-buffer-underflow
(reported via nua_create()).

Gate the stack fast path on a new SU_TAGARG_USE_TAGSTACK, which is
SU_HAVE_TAGSTACK && not AddressSanitizer (GCC __SANITIZE_ADDRESS__ or clang
__has_feature(address_sanitizer)), and use it for both ta_start() and ta_end().
Under ASan the existing portable va_list copy path (tl_vlist / tl_vfree) is used
instead, which does not walk below the frame. Normal builds are unchanged
(SU_TAGARG_USE_TAGSTACK == SU_HAVE_TAGSTACK); the ta_list layout (tagi_t tl[2])
is identical for both paths, so this is ABI-neutral.

Fixes freeswitch#210.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

heap buffer underflow in TAG_TYPE_OF(t)

1 participant