New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
qsort() interceptor broken on FreeBSD #46176
Labels
Comments
Fixed by 8803ebc. |
tobiasbrunner
added a commit
to strongswan/strongswan
that referenced
this issue
Sep 16, 2022
At least for the tests where it is available and works. It conflicts with the instrumentation used by the coverage and fuzzing (and possibly sonarcloud) tests, the toolchain for the Windows builds doesn't seem to support it, and on FreeBSD the test executables hang due to a compatibility issue with FreeBSD's qsort(), which has been fixed [1], but that has not made it into the clang version in the base system. [1] llvm/llvm-project#46176
tobiasbrunner
added a commit
to strongswan/strongswan
that referenced
this issue
Sep 16, 2022
At least for the tests where it is available and works. It conflicts with the instrumentation used by the coverage and fuzzing (and possibly sonarcloud) tests, the toolchain for the Windows builds doesn't seem to support it, and on FreeBSD the test executables hang due to a compatibility issue with FreeBSD's qsort(), which has been fixed [1], but that has not made it into the clang version in the base system. For the custom OpenSSL build, debug symbols are enabled so we can suppress some leaks properly. [1] llvm/llvm-project#46176
freebsd-git
pushed a commit
to freebsd/freebsd-ports
that referenced
this issue
Dec 11, 2023
I'd disabled it in 10.0.0 when it was found to be broken. It was then fixed in LLVM 12, but the patch was never never removed and I propogated it along for several year. Reported by: Brad Smith <brad@comstyle.com> See also: llvm/llvm-project#46176
This issue was closed.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Extended Description
The qsort interceptor results in an infinite loop on FreeBSD as can be seen from this backtrace:
0x00000000016b6d06 in wrapped_qsort_compar(void const*, void const*) ()
at /usr/local/poudriere/ports/brooks/devel/llvm-devel/work/llvm-project-61c2a0bb823677ce0e604b92e5dae65d9bd32b6e/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:9690
9690 return qsort_compar(a, b);
(gdb) bt
#0 0x00000000016b6d06 in wrapped_qsort_compar(void const*, void const*) ()
at /usr/local/poudriere/ports/brooks/devel/llvm-devel/work/llvm-project-61c2a0bb823677ce0e604b92e5dae65d9bd32b6e/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:9690
#1 0x0000000802efaa70 in qsort () from /lib/libc.so.7
#2 0x00000000016b6df3 in __interceptor_qsort ()
at /usr/local/poudriere/ports/brooks/devel/llvm-devel/work/llvm-project-61c2a0bb823677ce0e604b92e5dae65d9bd32b6e/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:9710
#3 0x0000000802efa99f in qsort () from /lib/libc.so.7
#4 0x00000000016b6df3 in __interceptor_qsort ()
at /usr/local/poudriere/ports/brooks/devel/llvm-devel/work/llvm-project-61c2a0bb823677ce0e604b92e5dae65d9bd32b6e/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:9710
#5 0x0000000001e9284f in llvm::array_pod_sort<std::__1::__wrap_iter<(anonymous namespace)::ELFWriter::ELFSymbolData*> > (Start=..., End=...)
at /exports/users/alr48/sources/llvm-project/llvm/include/llvm/ADT/STLExtras.h:1399
#6 0x0000000001e81e83 in (anonymous namespace)::ELFWriter::computeSymbolTable (this=0x7fffffffbf20, Asm=...,
Layout=..., SectionIndexMap=..., RevGroupMap=..., SectionOffsets=...)
The problem is that qsort() calls qsort() on individual parts of the array which ends up calling the interceptor again. However, the interceptor uses a thread local function pointer for the comparator wrapper.
The interceptor code does not handle this case:
qsort_compar_f old_compar = qsort_compar;
qsort_compar = compar;
SIZE_T old_size = qsort_size;
qsort_size = size;
REAL(qsort)(base, nmemb, size, wrapped_qsort_compar);
qsort_compar = old_compar;
qsort_size = old_size;
In the first call it will assign the real comparator to qsort_compar, but in the recursive call from inside qsort qsort_compar will end up being set to wrapped_qsort_compar and it ends up being an infinite loop.
The text was updated successfully, but these errors were encountered: