[libcxx-commits] [PATCH] D132522: [1b/3][compiler-rt][ASan] API for annotating objects memory

Vitaly Buka via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Sep 22 10:57:18 PDT 2022


vitalybuka requested changes to this revision.
vitalybuka added a comment.
This revision now requires changes to proceed.

Please update

  void TestContainer(size_t capacity, size_t begin_offset /* Fall for 0 .. 7 */) {

As-is the patch fails check-asan

Please update  compiler-rt/test/asan/TestCases/contiguous_container_crash.cpp

  // RUN: %clangxx_asan -O %s -o %t
  // RUN: not %run %t crash 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
  // RUN: not %run %t bad-bounds 2>&1 | FileCheck --check-prefix=CHECK-BAD-BOUNDS %s
  // RUN: not %run %t bad-alignment 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
  // RUN: not %run %t bad-alignment-end 2>&1 | FileCheck --check-prefix=CHECK-CRASH %s
  // RUN: %env_asan_opts=detect_container_overflow=0 %run %t crash
  //
  // Test crash due to __sanitizer_annotate_contiguous_container.
  
  #include <assert.h>
  #include <string.h>
  
  extern "C" {
  void __sanitizer_annotate_contiguous_container(const void *beg, const void *end,
                                                 const void *old_mid,
                                                 const void *new_mid);
  }  // extern "C"
  
  static volatile int one = 1;
  
  int TestCrash() {
    long t[100];
    t[60] = 0;
    __sanitizer_annotate_contiguous_container(&t[0], &t[0] + 100, &t[0] + 100,
                                              &t[0] + 50);
  // CHECK-CRASH: AddressSanitizer: container-overflow
  // CHECK-CRASH: if you don't care about these errors you may set ASAN_OPTIONS=detect_container_overflow=0
    return (int)t[60 * one];  // Touches the poisoned memory.
  }
  
  void BadBounds() {
    long t[100];
  // CHECK-BAD-BOUNDS: ERROR: AddressSanitizer: bad parameters to __sanitizer_annotate_contiguous_container
    __sanitizer_annotate_contiguous_container(&t[0], &t[0] + 100, &t[0] + 101,
                                              &t[0] + 50);
  }
  
  int BadAlignment() {
    int t[100];
    t[60] = 0;
    __sanitizer_annotate_contiguous_container(&t[1], &t[0] + 100, &t[0] + 100,
                                              &t[1] + 50);
    return (int)t[60 * one];  // Touches the poisoned memory.
  }
  
  int BadAlignmentEnd() {
    int t[99];
    t[60] = 0;
    __sanitizer_annotate_contiguous_container(&t[0], &t[0] + 99, &t[0] + 99,
                                              &t[0] + 50);
    return (int)t[60 * one];  // Touches the poisoned memory.
  }
  
  int main(int argc, char **argv) {
    assert(argc == 2);
    if (!strcmp(argv[1], "crash"))
      return TestCrash();
    else if (!strcmp(argv[1], "bad-bounds"))
      BadBounds();
    else if (!strcmp(argv[1], "bad-alignment"))
      return BadAlignment();
    else if (!strcmp(argv[1], "bad-alignment-end"))
      return BadAlignmentEnd();
    return 0;
  }



================
Comment at: compiler-rt/lib/asan/asan_poisoning.cpp:362
                                                  &stack);
   }
   CHECK_LE(end - beg,
----------------
```
void __sanitizer_annotate_contiguous_container(const void *beg_p,
                                               const void *end_p,
                                               const void *old_mid_p,
                                               const void *new_mid_p) {
  if (!flags()->detect_container_overflow) return;
  VPrintf(2, "contiguous_container: %p %p %p %p\n", beg_p, end_p, old_mid_p,
          new_mid_p);
  uptr beg = reinterpret_cast<uptr>(beg_p);
  uptr end = reinterpret_cast<uptr>(end_p);
  uptr old_mid = reinterpret_cast<uptr>(old_mid_p);
  uptr new_mid = reinterpret_cast<uptr>(new_mid_p);
  uptr granularity = ASAN_SHADOW_GRANULARITY;
  if (!(beg <= old_mid && beg <= new_mid && old_mid <= end && new_mid <= end)) {
    GET_STACK_TRACE_FATAL_HERE;
    ReportBadParamsToAnnotateContiguousContainer(beg, end, old_mid, new_mid,
                                                 &stack);
  }
  CHECK_LE(end - beg,
           FIRST_32_SECOND_64(1UL << 30, 1ULL << 40)); // Sanity check.

  if (old_mid == new_mid)
    return;  // Nothing to do here.

  // Handle misaligned end and cut it off.
  if (UNLIKELY(!AddrIsAlignedByGranularity(end))) {
    uptr end_down = RoundDownTo(end, granularity);
    // Either new or old mid must be in the granule to affect it.
    if (new_mid > end_down) {
      if (AddressIsPoisoned(end)) {
        *(u8 *)MemToShadow(end_down) = static_cast<u8>(new_mid - end_down);
      } else {
        // Something after the container - don't touch.
      }
    } else if (old_mid > end_down) {
      if (AddressIsPoisoned(end)) {
        *(u8 *)MemToShadow(end_down) = kAsanContiguousContainerOOBMagic;
      } else {
        // Something after the container - don't touch.
      }
    }

    if (beg >= end_down)
      return;  // Same granule.

    old_mid = Min(end_down, old_mid);
    new_mid = Min(end_down, new_mid);
  }

  // Handle misaligned begin and cut it off.
  if (UNLIKELY(!AddrIsAlignedByGranularity(beg))) {
    uptr beg_up = RoundUpTo(beg, granularity);
    uptr beg_down = RoundDownTo(beg, granularity);
    // As soon as we add first byte into container we will not be able to
    // determine the state of the byte before the container. So we assume it's
    // always unpoison.

    // Either new or old mid must be in the granule to affect it.
    if (new_mid < beg_up) {
      *(u8 *)MemToShadow(beg_down) = static_cast<u8>(new_mid - beg_down);
    } else if (old_mid < beg_up) {
      *(u8 *)MemToShadow(beg_down) = 0;
    }

    old_mid = Max(beg_up, old_mid);
    new_mid = Max(beg_up, new_mid);
  }

  if (old_mid == new_mid)
    return;

  uptr a = RoundDownTo(Min(old_mid, new_mid), granularity);
  uptr c = RoundUpTo(Max(old_mid, new_mid), granularity);
  uptr d1 = RoundDownTo(old_mid, granularity);
  // uptr d2 = RoundUpTo(old_mid, granularity);
  // Currently we should be in this state:
  // [a, d1) is good, [d2, c) is bad, [d1, d2) is partially good.
  // Make a quick sanity check that we are indeed in this state.
  //
  // FIXME: Two of these three checks are disabled until we fix
  // https://github.com/google/sanitizers/issues/258.
  // if (d1 != d2)
  //  CHECK_EQ(*(u8*)MemToShadow(d1), old_mid - d1);
  if (a + granularity <= d1)
    CHECK_EQ(*(u8*)MemToShadow(a), 0);
  // if (d2 + granularity <= c && c <= end)
  //   CHECK_EQ(*(u8 *)MemToShadow(c - granularity),
  //            kAsanContiguousContainerOOBMagic);

  uptr b1 = RoundDownTo(new_mid, granularity);
  uptr b2 = RoundUpTo(new_mid, granularity);
  // New state:
  // [a, b1) is good, [b2, c) is bad, [b1, b2) is partially good.
  PoisonShadow(a, b1 - a, 0);
  PoisonShadow(b2, c - b2, kAsanContiguousContainerOOBMagic);
  if (b1 != b2) {
    CHECK_EQ(b2 - b1, granularity);
    *(u8*)MemToShadow(b1) = static_cast<u8>(new_mid - b1);
  }
}
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132522/new/

https://reviews.llvm.org/D132522



More information about the libcxx-commits mailing list