[RFC] Exception-friendly ASan annotations of std::string
Jonathan Wakely
jwakely@redhat.com
Mon Jun 12 10:13:00 GMT 2017
On 12/06/17 11:11 +0100, Jonathan Wakely wrote:
>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');
>}
If you're *only* talking about std::string and not other
specializations of std::basic_string, then I agree that you won't get
std::bad_alloc if ASan always terminates the process. But you can
still get std::length_error.
More information about the Libstdc++
mailing list