* [PATCH] PR libstdc++/80893 Fix null dereference in vector<bool>
@ 2017-05-31 12:48 Jonathan Wakely
2017-06-17 12:12 ` Jonathan Wakely
0 siblings, 1 reply; 2+ messages in thread
From: Jonathan Wakely @ 2017-05-31 12:48 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 644 bytes --]
vector<bool> does addressof(*ptr) where ptr is returned by
allocate(n), but if n==0 that pointer might not be dereferencable.
While testing the fix I also found some bugs in the
__gnu_test::PointerBase helper that needed correcting.
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.
Tested powerpc64le-linux, committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 4680 bytes --]
commit bdb028b38ace766538150d5ef7874123d0689cd7
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Wed May 31 11:40:14 2017 +0100
PR libstdc++/80893 Fix null dereference in vector<bool>
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.
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index 37e000a..78195c1 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -1089,9 +1089,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
index 0000000..0545b38
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc
@@ -0,0 +1,74 @@
+// 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/>.
+
+// 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);
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h
index 813fc81..56c2708 100644
--- a/libstdc++-v3/testsuite/util/testsuite_allocator.h
+++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h
@@ -570,6 +570,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) { }
@@ -603,7 +605,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>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] PR libstdc++/80893 Fix null dereference in vector<bool>
2017-05-31 12:48 [PATCH] PR libstdc++/80893 Fix null dereference in vector<bool> Jonathan Wakely
@ 2017-06-17 12:12 ` Jonathan Wakely
0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Wakely @ 2017-06-17 12:12 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 852 bytes --]
On 31/05/17 13:45 +0100, Jonathan Wakely wrote:
>vector<bool> does addressof(*ptr) where ptr is returned by
>allocate(n), but if n==0 that pointer might not be dereferencable.
>
>While testing the fix I also found some bugs in the
>__gnu_test::PointerBase helper that needed correcting.
>
> 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.
>
>Tested powerpc64le-linux, committed to trunk.
The new test fails in C++98 modes, as shown at https://gcc.gnu.org/ml/gcc-testresults/2017-06/msg01833.html
Fixed like so, committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 773 bytes --]
commit c8315ef81030c2d3d284c2dc3d545419243216c3
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Sat Jun 17 12:46:18 2017 +0100
PR libstdc++/80893 don't run test for C++98 modes
PR libstdc++/80893
* testsuite/23_containers/vector/bool/80893.cc: Add { target c++11 }.
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc
index 0545b38..0b0016c 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/80893.cc
@@ -15,6 +15,8 @@
// 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>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-06-17 12:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-31 12:48 [PATCH] PR libstdc++/80893 Fix null dereference in vector<bool> Jonathan Wakely
2017-06-17 12:12 ` Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).