[PATCH] D71780: [msan] Check qsort input.

Evgenii Stepanov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 20 12:23:45 PST 2019


eugenis created this revision.
eugenis added a reviewer: vitalybuka.
Herald added projects: Sanitizers, LLVM.
Herald added a subscriber: Sanitizers.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71780

Files:
  compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
  compiler-rt/test/msan/qsort.cpp


Index: compiler-rt/test/msan/qsort.cpp
===================================================================
--- compiler-rt/test/msan/qsort.cpp
+++ compiler-rt/test/msan/qsort.cpp
@@ -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 @@
   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);
Index: compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -9665,6 +9665,15 @@
             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 @@
             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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D71780.234944.patch
Type: text/x-patch
Size: 2412 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191220/85167612/attachment.bin>


More information about the llvm-commits mailing list