Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -868,17 +868,17 @@ // but if an exception is thrown after that the annotation has to be undone. struct __RAII_IncreaseAnnotator { __RAII_IncreaseAnnotator(const vector &__v, size_type __n = 1) - : __commit(false), __v(__v), __n(__n) { + : __commit(false), __v(__v), __old_size(__v.size() + __n) { __v.__annotate_increase(__n); } void __done() { __commit = true; } ~__RAII_IncreaseAnnotator() { if (__commit) return; - __v.__annotate_shrink(__v.size() + __n); + __v.__annotate_shrink(__old_size); } bool __commit; - size_type __n; const vector &__v; + size_type __old_size; }; #else struct __RAII_IncreaseAnnotator { Index: test/std/containers/sequences/vector/asan_throw.pass.cpp =================================================================== --- test/std/containers/sequences/vector/asan_throw.pass.cpp +++ test/std/containers/sequences/vector/asan_throw.pass.cpp @@ -37,6 +37,22 @@ char a; }; +class ThrowOnCopy { +public: + ThrowOnCopy() : should_throw(false) {} + explicit ThrowOnCopy(bool should_throw) : should_throw(should_throw) {} + + ThrowOnCopy(ThrowOnCopy const & other) + : should_throw(other.should_throw) + { + if (should_throw) { + throw 0; + } + } + + bool should_throw; +}; + void test_push_back() { std::vector v; v.reserve(2); @@ -157,6 +173,23 @@ assert(0); } + +void test_insert_n2() { + std::vector v(10); + v.reserve(100); + assert(v.size() == 10); + v[6].should_throw = true; + try { + v.insert(v.cbegin(), 5, ThrowOnCopy()); + assert(0); + } catch (int e) { + assert(v.size() == 11); + assert(is_contiguous_container_asan_correct(v)); + return; + } + assert(0); +} + void test_resize() { std::vector v; v.reserve(3); @@ -193,6 +226,7 @@ test_emplace(); test_insert_range2(); test_insert_n(); + test_insert_n2(); test_resize(); test_resize_param(); }