]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libstdc++/59829 (Calling vector::data() occurs undefined behavior when the...
authorJonathan Wakely <jwakely@redhat.com>
Wed, 29 Jan 2014 14:57:42 +0000 (14:57 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 29 Jan 2014 14:57:42 +0000 (14:57 +0000)
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
libstdc++-v3/include/bits/stl_vector.h
libstdc++-v3/testsuite/23_containers/vector/59829.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc

index 9618c9eb275eeacac7c5a52ef6a848a779c456ec..9578071f478d2bc4e5b9ab7c4ff593e7922a9aec 100644 (file)
        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  <jwakely@redhat.com>
            Kyle Lippincott  <spectral@google.com>
 
index 98ac708e8f16ee9ad452c279c484380ae3f5f521..7e52fde55b1be4e9f8700f52bc50bf35e9b84a7b 100644 (file)
@@ -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<typename _Up>
+       _Up*
+       _M_data_ptr(_Up* __ptr) const
+       { return __ptr; }
+
+      template<typename _Ptr>
+       typename std::pointer_traits<_Ptr>::element_type*
+       _M_data_ptr(_Ptr __ptr) const
+       { return empty() ? nullptr : std::__addressof(*__ptr); }
+#else
+      template<typename _Ptr>
+       _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 (file)
index 0000000..1818c89
--- /dev/null
@@ -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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11" }
+
+// libstdc++/59829
+
+#include <vector>
+#include <testsuite_allocator.h>
+
+// User-defined pointer type that throws if a null pointer is dereferenced.
+template<typename T>
+struct Pointer : __gnu_test::PointerBase<Pointer<T>, T>
+{
+  using __gnu_test::PointerBase<Pointer<T>, T>::PointerBase;
+
+  T& operator*() const
+  {
+    if (!this->value)
+      throw "Dereferenced invalid pointer";
+    return *this->value;
+  }
+};
+
+// Minimal allocator using Pointer<T>
+template<typename T>
+struct Alloc
+{
+  typedef T value_type;
+  typedef Pointer<T> pointer;
+
+  Alloc() = default;
+  template<typename U>
+    Alloc(const Alloc<U>&) { }
+
+  pointer allocate(std::size_t n)
+  { return pointer(std::allocator<T>().allocate(n)); }
+
+  void deallocate(pointer p, std::size_t n)
+  { std::allocator<T>().deallocate(p.value, n); }
+};
+
+template<typename T>
+bool operator==(Alloc<T> l, Alloc<T> r) { return true; }
+
+template<typename T>
+bool operator!=(Alloc<T> l, Alloc<T> r) { return false; }
+
+int main()
+{
+  std::vector<int, Alloc<int>> a;
+  a.data();
+}
index a12b11673354115e3c1ed53daa796f816b6d0b9c..191fbc7bfdb3da4bc97f0d6363fddf75ef2eaaec 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1316 }
+// { dg-error "no matching" "" { target *-*-* } 1320 }
 
 #include <vector>
 
index b839cccc894a8b465c4bdc4eb8452e7104eecc50..8818a88ccd779805de42bd1099d96277b33bbaf7 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1242 }
+// { dg-error "no matching" "" { target *-*-* } 1246 }
 
 #include <vector>
 
index e9e966b792a81176d47fca66fde4fa235054cb15..09499bcbad7a6350b3b566e9b019c24f6bd9eac7 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1242 }
+// { dg-error "no matching" "" { target *-*-* } 1246 }
 
 #include <vector>
 #include <utility>
index 71c6c496e2abbb048612ee51e79f9fe16c2966f1..674e3b5d6e505420bb5a20b8d6fa3ce6e231dd4b 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1357 }
+// { dg-error "no matching" "" { target *-*-* } 1361 }
 
 #include <vector>