]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR libstdc++/80893 Fix null dereference in vector<bool>
authorJonathan Wakely <jwakely@redhat.com>
Wed, 8 Aug 2018 15:40:47 +0000 (16:40 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 8 Aug 2018 15:40:47 +0000 (16:40 +0100)
Backport from mainline
2017-06-17  Jonathan Wakely  <jwakely@redhat.com>

PR libstdc++/80893
* testsuite/23_containers/vector/bool/80893.cc: Add { target c++11 }.

Backport from mainline
2017-05-31  Jonathan Wakely  <jwakely@redhat.com>

PR libstdc++/80893
* include/bits/stl_bvector.h (vector<bool>::_M_initialize): Avoid
null pointer dereference when size is zero.
* testsuite/23_containers/vector/bool/80893.cc: New.
* testsuite/util/testsuite_allocator.h (PointerBase::PointerBase):
Add non-explicit constructor from nullptr.
(PointerBase::derived() const): Add const-qualified overload.

From-SVN: r263421

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_bvector.h
libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_allocator.h

index 9740f022408c9a74f59878916441681f44143088..751797110ebe4b56ec305f0fdc7962450a79b723 100644 (file)
@@ -1,5 +1,22 @@
 2018-08-08  Jonathan Wakely  <jwakely@redhat.com>
 
+       Backport from mainline
+       2017-06-17  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/80893
+       * testsuite/23_containers/vector/bool/80893.cc: Add { target c++11 }.
+
+       Backport from mainline
+       2017-05-31  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/80893
+       * include/bits/stl_bvector.h (vector<bool>::_M_initialize): Avoid
+       null pointer dereference when size is zero.
+       * testsuite/23_containers/vector/bool/80893.cc: New.
+       * testsuite/util/testsuite_allocator.h (PointerBase::PointerBase):
+       Add non-explicit constructor from nullptr.
+       (PointerBase::derived() const): Add const-qualified overload.
+
        Backport from mainline
        2017-12-14  Jonathan Wakely  <jwakely@redhat.com>
 
index 629fe4dd902554687bb15bda5627b93482ef1c12..e672a4f6b0efa5fbbbcdc80893477031d92590cf 100644 (file)
@@ -1078,9 +1078,17 @@ template<typename _Alloc>
     void
     _M_initialize(size_type __n)
     {
-      _Bit_pointer __q = this->_M_allocate(__n);
-      this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
-      this->_M_impl._M_start = iterator(std::__addressof(*__q), 0);
+      if (__n)
+       {
+         _Bit_pointer __q = this->_M_allocate(__n);
+         this->_M_impl._M_end_of_storage = __q + _S_nword(__n);
+         this->_M_impl._M_start = iterator(std::__addressof(*__q), 0);
+       }
+      else
+       {
+         this->_M_impl._M_end_of_storage = _Bit_pointer();
+         this->_M_impl._M_start = iterator(0, 0);
+       }
       this->_M_impl._M_finish = this->_M_impl._M_start + difference_type(__n);
     }
 
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc
new file mode 100644 (file)
index 0000000..0b0016c
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (C) 2017 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-do run { target c++11 } }
+
+// libstdc++/80893
+
+#include <vector>
+#include <testsuite_allocator.h>
+
+struct DereferencedInvalidPointer { };
+
+// 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 DereferencedInvalidPointer();
+    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)
+  {
+    if (n)
+      return pointer(std::allocator<T>().allocate(n));
+    return nullptr;
+  }
+
+  void deallocate(pointer p, std::size_t n)
+  {
+    if (n)
+      std::allocator<T>().deallocate(p.value, n);
+  }
+};
+
+template<typename T>
+bool operator==(Alloc<T>, Alloc<T>) { return true; }
+
+template<typename T>
+bool operator!=(Alloc<T>, Alloc<T>) { return false; }
+
+int main()
+{
+  std::vector<bool, Alloc<bool>> v(0);
+  std::vector<bool, Alloc<bool>> w(v);
+}
index f597a3846ab71c1665b238d30ab4c232a3634ca7..cdddf746cda6e614b43ec26f2193b6295022b1e3 100644 (file)
@@ -572,6 +572,8 @@ namespace __gnu_test
 
       explicit PointerBase(T* p = nullptr) : value(p) { }
 
+      PointerBase(std::nullptr_t) : value(nullptr) { }
+
       template<typename D, typename U,
               typename = decltype(static_cast<T*>(std::declval<U*>()))>
        PointerBase(const PointerBase<D, U>& p) : value(p.value) { }
@@ -605,7 +607,11 @@ namespace __gnu_test
       }
 
     private:
-      Derived& derived() { return static_cast<Derived&>(*this); }
+      Derived&
+      derived() { return static_cast<Derived&>(*this); }
+
+      const Derived&
+      derived() const { return static_cast<const Derived&>(*this); }
     };
 
     template<typename D, typename T>