From 8a972abdd98acac11c9882957ebf5e68d532948e Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 29 Jan 2014 14:57:42 +0000 Subject: [PATCH] re PR libstdc++/59829 (Calling vector::data() occurs undefined behavior when the vector is empty) PR libstdc++/59829 * include/bits/stl_vector.h (vector::data()): Call _M_data_ptr. (vector::_M_data_ptr): New overloaded functions to ensure empty vectors do not dereference the pointer. * testsuite/23_containers/vector/59829.cc: New. * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc: Adjust dg-error line number. * testsuite/23_containers/vector/requirements/dr438/ constructor_1_neg.cc: Likewise. * testsuite/23_containers/vector/requirements/dr438/ constructor_2_neg.cc: Likewise. * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc: Likewise. From-SVN: r207241 --- libstdc++-v3/ChangeLog | 14 ++++ libstdc++-v3/include/bits/stl_vector.h | 21 +++++- .../testsuite/23_containers/vector/59829.cc | 67 +++++++++++++++++++ .../vector/requirements/dr438/assign_neg.cc | 2 +- .../requirements/dr438/constructor_1_neg.cc | 2 +- .../requirements/dr438/constructor_2_neg.cc | 2 +- .../vector/requirements/dr438/insert_neg.cc | 2 +- 7 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/vector/59829.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9618c9eb275..9578071f478 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -24,6 +24,20 @@ New. * testsuite/20_util/allocator_traits/requirements/typedefs2.cc: New. + PR libstdc++/59829 + * include/bits/stl_vector.h (vector::data()): Call _M_data_ptr. + (vector::_M_data_ptr): New overloaded functions to ensure empty + vectors do not dereference the pointer. + * testsuite/23_containers/vector/59829.cc: New. + * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc: + Adjust dg-error line number. + * testsuite/23_containers/vector/requirements/dr438/ + constructor_1_neg.cc: Likewise. + * testsuite/23_containers/vector/requirements/dr438/ + constructor_2_neg.cc: Likewise. + * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc: + Likewise. + 2014-01-28 Jonathan Wakely Kyle Lippincott diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 98ac708e8f1..7e52fde55b1 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -888,7 +888,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER pointer #endif data() _GLIBCXX_NOEXCEPT - { return std::__addressof(front()); } + { return _M_data_ptr(this->_M_impl._M_start); } #if __cplusplus >= 201103L const _Tp* @@ -896,7 +896,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const_pointer #endif data() const _GLIBCXX_NOEXCEPT - { return std::__addressof(front()); } + { return _M_data_ptr(this->_M_impl._M_start); } // [23.2.4.3] modifiers /** @@ -1470,6 +1470,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } #endif + +#if __cplusplus >= 201103L + template + _Up* + _M_data_ptr(_Up* __ptr) const + { return __ptr; } + + template + typename std::pointer_traits<_Ptr>::element_type* + _M_data_ptr(_Ptr __ptr) const + { return empty() ? nullptr : std::__addressof(*__ptr); } +#else + template + _Ptr + _M_data_ptr(_Ptr __ptr) const + { return __ptr; } +#endif }; diff --git a/libstdc++-v3/testsuite/23_containers/vector/59829.cc b/libstdc++-v3/testsuite/23_containers/vector/59829.cc new file mode 100644 index 00000000000..1818c8941ec --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/59829.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++11" } + +// libstdc++/59829 + +#include +#include + +// User-defined pointer type that throws if a null pointer is dereferenced. +template +struct Pointer : __gnu_test::PointerBase, T> +{ + using __gnu_test::PointerBase, T>::PointerBase; + + T& operator*() const + { + if (!this->value) + throw "Dereferenced invalid pointer"; + return *this->value; + } +}; + +// Minimal allocator using Pointer +template +struct Alloc +{ + typedef T value_type; + typedef Pointer pointer; + + Alloc() = default; + template + Alloc(const Alloc&) { } + + pointer allocate(std::size_t n) + { return pointer(std::allocator().allocate(n)); } + + void deallocate(pointer p, std::size_t n) + { std::allocator().deallocate(p.value, n); } +}; + +template +bool operator==(Alloc l, Alloc r) { return true; } + +template +bool operator!=(Alloc l, Alloc r) { return false; } + +int main() +{ + std::vector> a; + a.data(); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc index a12b1167335..191fbc7bfdb 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1316 } +// { dg-error "no matching" "" { target *-*-* } 1320 } #include diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc index b839cccc894..8818a88ccd7 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1242 } +// { dg-error "no matching" "" { target *-*-* } 1246 } #include diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc index e9e966b792a..09499bcbad7 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1242 } +// { dg-error "no matching" "" { target *-*-* } 1246 } #include #include diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc index 71c6c496e2a..674e3b5d6e5 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc @@ -18,7 +18,7 @@ // . // { dg-do compile } -// { dg-error "no matching" "" { target *-*-* } 1357 } +// { dg-error "no matching" "" { target *-*-* } 1361 } #include