diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -9855,12 +9855,19 @@ } } qsort_compar_f old_compar = qsort_compar; - qsort_compar = compar; SIZE_T old_size = qsort_size; - qsort_size = size; + // Handle qsort() implementations that recurse using an + // interposable function call: + bool already_wrapped = compar == wrapped_qsort_compar; + if (!already_wrapped) { + qsort_compar = compar; + qsort_size = size; + } REAL(qsort)(base, nmemb, size, wrapped_qsort_compar); - qsort_compar = old_compar; - qsort_size = old_size; + if (!already_wrapped) { + qsort_compar = old_compar; + qsort_size = old_size; + } COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); } #define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort) @@ -9893,12 +9900,19 @@ } } qsort_r_compar_f old_compar = qsort_r_compar; - qsort_r_compar = compar; SIZE_T old_size = qsort_r_size; - qsort_r_size = size; + // Handle qsort_r() implementations that recurse using an + // interposable function call: + bool already_wrapped = compar == wrapped_qsort_r_compar; + if (!already_wrapped) { + qsort_r_compar = compar; + qsort_r_size = size; + } REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg); - qsort_r_compar = old_compar; - qsort_r_size = old_size; + if (!already_wrapped) { + qsort_r_compar = old_compar; + qsort_r_size = old_size; + } COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size); } #define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)