@@ -9951,13 +9951,17 @@ INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
9951
9951
9952
9952
#if SANITIZER_INTERCEPT_QSORT_R
9953
9953
typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
9954
- static THREADLOCAL qsort_r_compar_f qsort_r_compar;
9955
- static THREADLOCAL SIZE_T qsort_r_size;
9954
+ struct qsort_r_compar_params {
9955
+ SIZE_T size;
9956
+ qsort_r_compar_f compar;
9957
+ void *arg;
9958
+ };
9956
9959
static int wrapped_qsort_r_compar(const void *a, const void *b, void *arg) {
9960
+ qsort_r_compar_params *params = (qsort_r_compar_params *)arg;
9957
9961
COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
9958
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, qsort_r_size );
9959
- COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, qsort_r_size );
9960
- return qsort_r_compar (a, b, arg);
9962
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, params->size );
9963
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, params->size );
9964
+ return params->compar (a, b, params-> arg);
9961
9965
}
9962
9966
9963
9967
INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
@@ -9973,34 +9977,24 @@ INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
9973
9977
compar(p, q, arg);
9974
9978
}
9975
9979
}
9976
- qsort_r_compar_f old_compar = qsort_r_compar;
9977
- SIZE_T old_size = qsort_r_size;
9978
- // Handle qsort_r() implementations that recurse using an
9979
- // interposable function call:
9980
- bool already_wrapped = compar == wrapped_qsort_r_compar;
9981
- if (already_wrapped) {
9982
- // This case should only happen if the qsort() implementation calls itself
9983
- // using a preemptible function call (e.g. the FreeBSD libc version).
9984
- // Check that the size and comparator arguments are as expected.
9985
- CHECK_NE(compar, qsort_r_compar);
9986
- CHECK_EQ(qsort_r_size, size);
9987
- } else {
9988
- qsort_r_compar = compar;
9989
- qsort_r_size = size;
9990
- }
9991
- REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg);
9992
- if (!already_wrapped) {
9993
- qsort_r_compar = old_compar;
9994
- qsort_r_size = old_size;
9995
- }
9980
+ qsort_r_compar_params params = {size, compar, arg};
9981
+ REAL(qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, ¶ms);
9996
9982
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
9997
9983
}
9998
9984
# define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION(qsort_r)
9999
9985
#else
10000
9986
# define INIT_QSORT_R
10001
9987
#endif
10002
9988
10003
- #if SANITIZER_INTERCEPT_QSORT
9989
+ #if SANITIZER_INTERCEPT_QSORT && SANITIZER_INTERCEPT_QSORT_R
9990
+ INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
9991
+ qsort_r_compar_f compar) {
9992
+ void *ctx;
9993
+ COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
9994
+ WRAP(qsort_r)(base, nmemb, size, compar, nullptr);
9995
+ }
9996
+ # define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
9997
+ #elif SANITIZER_INTERCEPT_QSORT && !SANITIZER_INTERCEPT_QSORT_R
10004
9998
// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
10005
9999
// Poisoned memory from there may get copied into the comparator arguments,
10006
10000
// where it needs to be dealt with. But even that is not enough - the results of
@@ -10057,29 +10051,30 @@ INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
10057
10051
}
10058
10052
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, base, nmemb * size);
10059
10053
}
10060
- #define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
10054
+ # define INIT_QSORT COMMON_INTERCEPT_FUNCTION(qsort)
10061
10055
#else
10062
- #define INIT_QSORT
10056
+ # define INIT_QSORT
10063
10057
#endif
10064
10058
10065
10059
#if SANITIZER_INTERCEPT_BSEARCH
10066
10060
typedef int (*bsearch_compar_f)(const void *, const void *);
10067
- static THREADLOCAL bsearch_compar_f bsearch_compar;
10068
- static int wrapped_bsearch_compar(const void *a, const void *b) {
10061
+ struct bsearch_compar_params {
10062
+ const void *key;
10063
+ bsearch_compar_f compar;
10064
+ };
10065
+
10066
+ static int wrapped_bsearch_compar(const void *key, const void *b) {
10067
+ const bsearch_compar_params *params = (const bsearch_compar_params *)key;
10069
10068
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
10070
- return bsearch_compar(a , b);
10069
+ return params->compar(params->key , b);
10071
10070
}
10072
10071
10073
10072
INTERCEPTOR(void *, bsearch, const void *key, const void *base, SIZE_T nmemb,
10074
10073
SIZE_T size, bsearch_compar_f compar) {
10075
10074
void *ctx;
10076
10075
COMMON_INTERCEPTOR_ENTER(ctx, bsearch, key, base, nmemb, size, compar);
10077
- // Unlike qsort, don't expect recursive implementation of bsearch.
10078
- CHECK_NE(compar, wrapped_bsearch_compar);
10079
- Swap(bsearch_compar, compar);
10080
- void *r = REAL(bsearch)(key, base, nmemb, size, wrapped_bsearch_compar);
10081
- bsearch_compar = compar;
10082
- return r;
10076
+ bsearch_compar_params params = {key, compar};
10077
+ return REAL(bsearch)(¶ms, base, nmemb, size, wrapped_bsearch_compar);
10083
10078
}
10084
10079
# define INIT_BSEARCH COMMON_INTERCEPT_FUNCTION(bsearch)
10085
10080
#else
0 commit comments