[all-commits] [llvm/llvm-project] 9a5f28: [2a/3][ASan][libcxx] std::deque annotations

Tacet via All-commits all-commits at lists.llvm.org
Fri May 5 09:11:47 PDT 2023


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 9a5f283139201ba5878780c06c97e4ad1f5eac39
      https://github.com/llvm/llvm-project/commit/9a5f283139201ba5878780c06c97e4ad1f5eac39
  Author: Advenam Tacet <advenam.tacet at trailofbits.com>
  Date:   2023-05-05 (Fri, 05 May 2023)

  Changed paths:
    M libcxx/include/__config
    M libcxx/include/deque
    A libcxx/test/libcxx/containers/sequences/deque/asan.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.capacity/access.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.capacity/empty.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.capacity/max_size.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.capacity/resize_size_value.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.capacity/shrink_to_fit.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.capacity/size.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/alloc.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/assign_initializer_list.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/assign_iter_iter.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/assign_size_value.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/copy.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/copy_alloc.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/deduct.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/default.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/initializer_list_alloc.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/iter_iter_alloc.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/move.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/move_alloc.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/move_assign.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/op_equal.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/op_equal_initializer_list.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/size.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/size_value.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.cons/size_value_alloc.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.erasure/erase.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.erasure/erase_if.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/clear.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_back.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/emplace_front.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.invalidation.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.invalidation.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/erase_iter_iter.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_initializer_list.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_iter_iter.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_rvalue.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_size_value.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/insert_value.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.invalidation.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_back.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.invalidation.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/pop_front.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/push_back_rvalue.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.modifiers/push_front_rvalue.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.special/copy.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.special/copy_backward.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.special/move.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.special/move_backward.pass.cpp
    M libcxx/test/std/containers/sequences/deque/deque.special/swap.pass.cpp
    M libcxx/test/support/asan_testing.h

  Log Message:
  -----------
  [2a/3][ASan][libcxx] std::deque annotations

This revision is a part of a series of patches extending AddressSanitizer C++ container overflow detection capabilities by adding annotations, similar to those existing in std::vector, to std::string and `std::deque` collections. These changes allow ASan to detect cases when the instrumented program accesses memory which is internally allocated by the collection but is still not in-use (accesses before or after the stored elements for `std::deque`, or between the size and capacity bounds for `std::string`).

The motivation for the research and those changes was a bug, found by Trail of Bits, in a real code where an out-of-bounds read could happen as two strings were compared via a std::equals function that took `iter1_begin`, `iter1_end`, `iter2_begin` iterators (with a custom comparison function). When object `iter1` was longer than `iter2`, read out-of-bounds on `iter2` could happen. Container sanitization would detect it.

This revision introduces annotations for `std::deque`. Each chunk of the container can now be annotated using the `__sanitizer_annotate_double_ended_contiguous_container` function, which was added in the rG1c5ad6d2c01294a0decde43a88e9c27d7437d157. Any attempt to access poisoned memory will trigger an ASan error. Although false negatives are rare, they are possible due to limitations in the ASan API, where a few (usually up to 7) bytes before the container may remain unpoisoned. There are no false positives in the same way as with `std::vector` annotations.

This patch only supports objects (deques) that use the standard allocator. However, it can be easily extended to support all allocators, as suggested in the D146815 revision.

Furthermore, the patch includes the addition of the `is_double_ended_contiguous_container_asan_correct` function to libcxx/test/support/asan_testing.h. This function can be used to verify whether a `std::deque` object has been correctly annotated.

Finally, the patch extends the unit tests to verify ASan annotations (added LIBCPP_ASSERTs).
If a program is compiled without ASan, all helper functions will be no-ops. In binaries with ASan, there is a negligible performance impact since the code from the change is only executed when the deque container changes in size and it’s proportional to the change. It is important to note that regardless of whether or not these changes are in use, every access to the container's memory is instrumented.

Reviewed By: #libc, philnik

Spies: mikhail.ramalho, Enna1, #sanitizers, philnik, libcxx-commits

Differential Revision: https://reviews.llvm.org/D132092




More information about the All-commits mailing list