This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


On 13/06/17 14:14 +0300, Ivan Baravy wrote:


On 06/12/2017 01:13 PM, Jonathan Wakely wrote:
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?

Exactly, sorry if I was unclear about that.
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');
}

ASan makes some assumptions on allocator's behavior (e.g. alignment).
Therefore I follow design of ASan annotations in libc++ and enable
sanitizer checks for std::allocator only. Perhaps, If I write a custom
allocator that will meet requirements of ASan and throw bad_alloc or
length_error 'by request', then I can test my implementation easily.
Thank you for hints to this idea.

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


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.

Yes, I talk about std::string only, at least for now. I've been

It's definitely OK to ignore std::bad_alloc then.

rethinking this last days and now agree that std::length_error is still
to be considered. It seems I wanted a small, fast but wrong design.

Yes, this will throw a length_error without calling any allocation
function:

std::string().resize(std::string().max_size()+1);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]