@@ -9949,6 +9949,57 @@ INTERCEPTOR(int, getentropy, void *buf, SIZE_T buflen) {
9949
9949
#define INIT_GETENTROPY
9950
9950
#endif
9951
9951
9952
+ #if SANITIZER_INTERCEPT_QSORT_R
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;
9956
+ static int wrapped_qsort_r_compar (const void *a, const void *b, void *arg) {
9957
+ 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);
9961
+ }
9962
+
9963
+ INTERCEPTOR (void , qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
9964
+ qsort_r_compar_f compar, void *arg) {
9965
+ void *ctx;
9966
+ COMMON_INTERCEPTOR_ENTER (ctx, qsort_r, base, nmemb, size, compar, arg);
9967
+ // Run the comparator over all array elements to detect any memory issues.
9968
+ if (nmemb > 1 ) {
9969
+ for (SIZE_T i = 0 ; i < nmemb - 1 ; ++i) {
9970
+ void *p = (void *)((char *)base + i * size);
9971
+ void *q = (void *)((char *)base + (i + 1 ) * size);
9972
+ COMMON_INTERCEPTOR_UNPOISON_PARAM (3 );
9973
+ compar (p, q, arg);
9974
+ }
9975
+ }
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
+ }
9996
+ COMMON_INTERCEPTOR_WRITE_RANGE (ctx, base, nmemb * size);
9997
+ }
9998
+ # define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION (qsort_r)
9999
+ #else
10000
+ # define INIT_QSORT_R
10001
+ #endif
10002
+
9952
10003
#if SANITIZER_INTERCEPT_QSORT
9953
10004
// Glibc qsort uses a temporary buffer allocated either on stack or on heap.
9954
10005
// Poisoned memory from there may get copied into the comparator arguments,
@@ -10011,57 +10062,6 @@ INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
10011
10062
#define INIT_QSORT
10012
10063
#endif
10013
10064
10014
- #if SANITIZER_INTERCEPT_QSORT_R
10015
- typedef int (*qsort_r_compar_f)(const void *, const void *, void *);
10016
- static THREADLOCAL qsort_r_compar_f qsort_r_compar;
10017
- static THREADLOCAL SIZE_T qsort_r_size;
10018
- static int wrapped_qsort_r_compar (const void *a, const void *b, void *arg) {
10019
- COMMON_INTERCEPTOR_UNPOISON_PARAM (3 );
10020
- COMMON_INTERCEPTOR_INITIALIZE_RANGE (a, qsort_r_size);
10021
- COMMON_INTERCEPTOR_INITIALIZE_RANGE (b, qsort_r_size);
10022
- return qsort_r_compar (a, b, arg);
10023
- }
10024
-
10025
- INTERCEPTOR (void , qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
10026
- qsort_r_compar_f compar, void *arg) {
10027
- void *ctx;
10028
- COMMON_INTERCEPTOR_ENTER (ctx, qsort_r, base, nmemb, size, compar, arg);
10029
- // Run the comparator over all array elements to detect any memory issues.
10030
- if (nmemb > 1 ) {
10031
- for (SIZE_T i = 0 ; i < nmemb - 1 ; ++i) {
10032
- void *p = (void *)((char *)base + i * size);
10033
- void *q = (void *)((char *)base + (i + 1 ) * size);
10034
- COMMON_INTERCEPTOR_UNPOISON_PARAM (3 );
10035
- compar (p, q, arg);
10036
- }
10037
- }
10038
- qsort_r_compar_f old_compar = qsort_r_compar;
10039
- SIZE_T old_size = qsort_r_size;
10040
- // Handle qsort_r() implementations that recurse using an
10041
- // interposable function call:
10042
- bool already_wrapped = compar == wrapped_qsort_r_compar;
10043
- if (already_wrapped) {
10044
- // This case should only happen if the qsort() implementation calls itself
10045
- // using a preemptible function call (e.g. the FreeBSD libc version).
10046
- // Check that the size and comparator arguments are as expected.
10047
- CHECK_NE (compar, qsort_r_compar);
10048
- CHECK_EQ (qsort_r_size, size);
10049
- } else {
10050
- qsort_r_compar = compar;
10051
- qsort_r_size = size;
10052
- }
10053
- REAL (qsort_r)(base, nmemb, size, wrapped_qsort_r_compar, arg);
10054
- if (!already_wrapped) {
10055
- qsort_r_compar = old_compar;
10056
- qsort_r_size = old_size;
10057
- }
10058
- COMMON_INTERCEPTOR_WRITE_RANGE (ctx, base, nmemb * size);
10059
- }
10060
- #define INIT_QSORT_R COMMON_INTERCEPT_FUNCTION (qsort_r)
10061
- #else
10062
- #define INIT_QSORT_R
10063
- #endif
10064
-
10065
10065
#if SANITIZER_INTERCEPT_BSEARCH
10066
10066
typedef int (*bsearch_compar_f)(const void *, const void *);
10067
10067
static THREADLOCAL bsearch_compar_f bsearch_compar;
0 commit comments