forked from OSchip/llvm-project
[msan] Check qsort input.
Summary: Qsort interceptor suppresses all checks by unpoisoning the data in the wrapper of a comparator function, and then unpoisoning the output array as well. This change adds an explicit run of the comparator on all elements of the input array to catch any sanitizer bugs. Reviewers: vitalybuka Subscribers: #sanitizers, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D71780
This commit is contained in:
parent
7a9ebe9512
commit
caa48a6b88
|
@ -9665,6 +9665,15 @@ INTERCEPTOR(void, qsort, void *base, SIZE_T nmemb, SIZE_T size,
|
|||
qsort_compar_f compar) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, qsort, base, nmemb, size, compar);
|
||||
// Run the comparator over all array elements to detect any memory issues.
|
||||
for (SIZE_T i = 0; i < nmemb; ++i) {
|
||||
void *p = (void *)((char *)base + i * size);
|
||||
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
|
||||
// Compare each element with itself to trigger an equality check, which
|
||||
// typically requires the comparator to look as many of the object fields as
|
||||
// possible.
|
||||
compar(p, p);
|
||||
}
|
||||
qsort_compar_f old_compar = qsort_compar;
|
||||
qsort_compar = compar;
|
||||
SIZE_T old_size = qsort_size;
|
||||
|
@ -9694,6 +9703,15 @@ INTERCEPTOR(void, qsort_r, void *base, SIZE_T nmemb, SIZE_T size,
|
|||
qsort_r_compar_f compar, void *arg) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, qsort_r, base, nmemb, size, compar, arg);
|
||||
// Run the comparator over all array elements to detect any memory issues.
|
||||
for (SIZE_T i = 0; i < nmemb; ++i) {
|
||||
void *p = (void *)((char *)base + i * size);
|
||||
COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
|
||||
// Compare each element with itself to trigger an equality check, which
|
||||
// typically requires the comparator to look as many of the object fields as
|
||||
// possible.
|
||||
compar(p, p, arg);
|
||||
}
|
||||
qsort_r_compar_f old_compar = qsort_r_compar;
|
||||
qsort_r_compar = compar;
|
||||
SIZE_T old_size = qsort_r_size;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: %clangxx_msan -O0 -g %s -o %t && %run %t
|
||||
// RUN: %clangxx_msan -DPOISON -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
@ -65,6 +66,10 @@ int main(int argc, char *argv[]) {
|
|||
for (int i = 0; i < kSize1; ++i)
|
||||
p[i] = i * 2 + (i % 3 - 1) * 3;
|
||||
poison_stack_and_param();
|
||||
#ifdef POISON
|
||||
__msan_poison(p + 1, sizeof(long));
|
||||
// CHECK: Uninitialized bytes in __msan_check_mem_is_initialized at offset 0 inside [{{.*}}, 8)
|
||||
#endif
|
||||
qsort(p, kSize1, sizeof(long), compar1);
|
||||
__msan_check_mem_is_initialized(p, sizeof(long) * kSize1);
|
||||
assert(seen2);
|
||||
|
|
Loading…
Reference in New Issue