aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2018-10-30 14:49:32 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2018-10-30 14:49:32 +0000
commitc397f267f1d0e8ea286904bc5543829b558e154f (patch)
tree39eea78abae2ee13849342bec8b4a18828ac862b /libstdc++-v3
parent47abbc3196ebf5829e8552d8824665af4c8a5c6f (diff)
downloadgcc-c397f267f1d0e8ea286904bc5543829b558e154f.zip
gcc-c397f267f1d0e8ea286904bc5543829b558e154f.tar.gz
gcc-c397f267f1d0e8ea286904bc5543829b558e154f.tar.bz2
PR libstdc++/87784 fix dynamic_bitset::push_back
Previously the _M_Nb member was incremented before calling _M_unchecked_set which meant that the bit being set was out of bounds. It either set the wrong bit in an allocated word, or accessed beyond the end of the allocated memory in the _M_w vector. The fix for the bug is to update the _M_Nb member after using it as an index. As an optimisation, when a new block needs to be appended the call to _M_unchecked_set can be avoided by appending a block with the least significant bit already set to the desired value. PR libstdc++/87784 * include/tr2/dynamic_bitset (dynamic_bitset::push_back): When there are no unused bits in the last block, append a new block with the right value so the bit doesn't need to be set. Only increment size after setting the new bit, not before. * testsuite/tr2/dynamic_bitset/pr87784.cc: New test. From-SVN: r265625
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset7
-rw-r--r--libstdc++-v3/testsuite/tr2/dynamic_bitset/pr87784.cc76
3 files changed, 89 insertions, 3 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index a3a4056..145eaa8 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2018-10-30 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/87784
+ * include/tr2/dynamic_bitset (dynamic_bitset::push_back): When there
+ are no unused bits in the last block, append a new block with the
+ right value so the bit doesn't need to be set. Only increment size
+ after setting the new bit, not before.
+ * testsuite/tr2/dynamic_bitset/pr87784.cc: New test.
+
2018-10-29 David Malcolm <dmalcolm@redhat.com>
* testsuite/17_intro/using_namespace_std_exp_neg.cc: Remove
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset
index f76c8fa..9e5c817 100644
--- a/libstdc++-v3/include/tr2/dynamic_bitset
+++ b/libstdc++-v3/include/tr2/dynamic_bitset
@@ -727,10 +727,11 @@ namespace tr2
void
push_back(bool __bit)
{
- if (size_t __offset = this->size() % bits_per_block == 0)
- this->_M_do_append_block(block_type(0), this->_M_Nb);
+ if (this->size() % bits_per_block == 0)
+ this->_M_do_append_block(block_type(__bit), this->_M_Nb);
+ else
+ this->_M_unchecked_set(this->_M_Nb, __bit);
++this->_M_Nb;
- this->_M_unchecked_set(this->_M_Nb, __bit);
}
/**
diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr87784.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr87784.cc
new file mode 100644
index 0000000..52dc3893
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/pr87784.cc
@@ -0,0 +1,76 @@
+// Copyright (C) 2018 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 } }
+
+#include <tr2/dynamic_bitset>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::tr2::dynamic_bitset<unsigned> b;
+ VERIFY( b.size() == 0 );
+ VERIFY( b.find_first() == b.size() );
+ b.push_back(0);
+ VERIFY( b.size() == 1 );
+ VERIFY( b.find_first() == b.size() );
+ b.push_back(0);
+ VERIFY( b.size() == 2 );
+ VERIFY( b.find_first() == b.size() );
+
+ b.push_back(1);
+ VERIFY( b.size() == 3 );
+ VERIFY( b.find_first() == b.size() - 1 );
+ b.push_back(1);
+ VERIFY( b.size() == 4 );
+ VERIFY( b.find_first() == b.size() - 2 );
+ b.push_back(0);
+ VERIFY( b.size() == 5 );
+ VERIFY( b.find_first() == b.size() - 3 );
+
+ b.clear();
+ VERIFY( b.size() == 0 );
+ VERIFY( b.find_first() == b.size() );
+ b.push_back(1);
+ VERIFY( b.size() == 1 );
+ VERIFY( b.find_first() == 0 );
+ b.push_back(1);
+ VERIFY( b.size() == 2 );
+ VERIFY( b.find_first() == 0 );
+ b.push_back(1);
+ VERIFY( b.size() == 3 );
+ VERIFY( b.find_first() == 0 );
+
+ b.clear();
+ b.append(2u);
+ VERIFY( b.size() == b.bits_per_block );
+ VERIFY( b.find_first() == 1 );
+ b <<= 1;
+ VERIFY( b.find_first() == 2 );
+ b <<= 3;
+ VERIFY( b.find_first() == 5 );
+ b <<= 6;
+ VERIFY( b.find_first() == 11 );
+ VERIFY( b.size() == b.bits_per_block );
+}
+
+int
+main()
+{
+ test01();
+}