[RFC] Exception-friendly ASan annotations of std::string

Jonathan Wakely jwakely@redhat.com
Mon Jun 12 10:11:00 GMT 2017


On 09/06/17 23:43 +0300, Ivan Baravy wrote:
>Hello,
>
>I'm working on address sanitization of standard containers. The aim is
>to detect and report accesses between size and capacity. The issue I
>faced is related to std::length_error and std::bad_alloc exceptions. I
>can get std::bad_alloc via huge fill insert into std::string. ASan adds
>a memory overhead (internal structures) to user allocations and, when
>enabled, it intercepts memory-related functions, failed allocations of
>vital structures make it terminate the process. Thus it looks like
>pointless for ASan annotations to be friendly to std::length_error and
>std::bad_alloc exceptions.
>
>So my question is if it's acceptable to not consider std::length_error
>and std::bad_alloc in address sanitization design?

I'm not sure if I understand the question, sorry.

ASan makes failed allocations call terminate, so you'll never get
std::bad_alloc from operator new, is that right?

But what does that have to do with std::length_error?

And you could still std::get bad_alloc from custom allocators, for
example the following throws std::bad_alloc without ever attempting to
allocate memory using operator new, or malloc:

#include <string>
#include <memory>

char buf[1024];
char* last = buf;

template<class T>
struct Alloc {
  using value_type = T;
  Alloc() { }
  template<typename U> Alloc(const Alloc<U>&) { }

  T* allocate(std::size_t n) {
    void* p = last;
    if (std::size_t(-1) / sizeof(T) > n)
      throw std::bad_alloc();
    n *= sizeof(T);
    std::size_t space = 1024 - (last - buf);
    if (!std::align(alignof(T), n, p, space))
      throw std::bad_alloc();
    last = (char*)p + n;
    return (T*)p;
  }

  void deallocate(T* p, std::size_t n) {
    n *= sizeof(T);
    char* pc = (char*)p;
    if (last == pc + n)
      last = pc;
  }

  template<typename U> bool operator==(Alloc<U>) const { return true; }
  template<typename U> bool operator!=(Alloc<U>) const { return false; }
};

int main()
{
  std::basic_string<char, std::char_traits<char>, Alloc<char>> s(1025, 'a');
}



More information about the Libstdc++ mailing list