Skip to content

Commit d5786bc

Browse files
committed
Merge bitcoin/bitcoin#32490: refactor: Remove UB in prevector reverse iterators
faf9082 test: Fix whitespace in prevector_tests.cpp (MarcoFalke) fa7f04c refactor: Remove UB in prevector reverse iterators (MarcoFalke) Pull request description: `rend()` creates a pointer with offset `-1`. This is UB, according to the C++ standard: https://eel.is/c++draft/expr.add#4: When an expression J that has integral type is added to [...] an expression P of pointer type, the result has the type of P. ... if P points to a (possibly-hypothetical) array element i of an array object x with n elements [...] the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) array element i+j of x if 0≤i+j≤n [...] Otherwise, the behavior is undefined. Also, it is unclear why the functions exist at all, when stdlib utils such as `std::reverse_iterator{it}` or `std::views::reverse` can be used out of the box. So remove them, along with the ubsan suppressions, that are no longer used. I've tagged this a refactor, because the code was always dead (unused outside of tests). And since commit 2925bd5 it was completely dead. Also, I could not find a sanitizer that detects this type of UB. ACKs for top commit: l0rinc: tested ACK faf9082 achow101: ACK faf9082 stickies-v: ACK faf9082, nice find. theuni: utACK faf9082 Tree-SHA512: 31511d520a1c0fdd65c2e5f1a8ef6fd17464303b6bff88a5d9d9577adfee849d431deb510882b6f4e15e8fb7168861bc0d26fca3bed4278f57a9d6e7b1235dce
2 parents 53eb559 + faf9082 commit d5786bc

File tree

3 files changed

+58
-84
lines changed

3 files changed

+58
-84
lines changed

src/prevector.h

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2015-2022 The Bitcoin Core developers
1+
// Copyright (c) 2015-present The Bitcoin Core developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

@@ -77,26 +77,6 @@ class prevector {
7777
bool operator<(iterator x) const { return ptr < x.ptr; }
7878
};
7979

80-
class reverse_iterator {
81-
T* ptr{};
82-
public:
83-
typedef Diff difference_type;
84-
typedef T value_type;
85-
typedef T* pointer;
86-
typedef T& reference;
87-
typedef std::bidirectional_iterator_tag iterator_category;
88-
reverse_iterator() = default;
89-
reverse_iterator(T* ptr_) : ptr(ptr_) {}
90-
T& operator*() const { return *ptr; }
91-
T* operator->() const { return ptr; }
92-
reverse_iterator& operator--() { ptr++; return *this; }
93-
reverse_iterator& operator++() { ptr--; return *this; }
94-
reverse_iterator operator++(int) { reverse_iterator copy(*this); ++(*this); return copy; }
95-
reverse_iterator operator--(int) { reverse_iterator copy(*this); --(*this); return copy; }
96-
bool operator==(reverse_iterator x) const { return ptr == x.ptr; }
97-
bool operator!=(reverse_iterator x) const { return ptr != x.ptr; }
98-
};
99-
10080
class const_iterator {
10181
const T* ptr{};
10282
public:
@@ -129,27 +109,6 @@ class prevector {
129109
bool operator<(const_iterator x) const { return ptr < x.ptr; }
130110
};
131111

132-
class const_reverse_iterator {
133-
const T* ptr{};
134-
public:
135-
typedef Diff difference_type;
136-
typedef const T value_type;
137-
typedef const T* pointer;
138-
typedef const T& reference;
139-
typedef std::bidirectional_iterator_tag iterator_category;
140-
const_reverse_iterator() = default;
141-
const_reverse_iterator(const T* ptr_) : ptr(ptr_) {}
142-
const_reverse_iterator(reverse_iterator x) : ptr(&(*x)) {}
143-
const T& operator*() const { return *ptr; }
144-
const T* operator->() const { return ptr; }
145-
const_reverse_iterator& operator--() { ptr++; return *this; }
146-
const_reverse_iterator& operator++() { ptr--; return *this; }
147-
const_reverse_iterator operator++(int) { const_reverse_iterator copy(*this); ++(*this); return copy; }
148-
const_reverse_iterator operator--(int) { const_reverse_iterator copy(*this); --(*this); return copy; }
149-
bool operator==(const_reverse_iterator x) const { return ptr == x.ptr; }
150-
bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; }
151-
};
152-
153112
private:
154113
#pragma pack(push, 1)
155114
union direct_or_indirect {
@@ -304,11 +263,6 @@ class prevector {
304263
iterator end() { return iterator(item_ptr(size())); }
305264
const_iterator end() const { return const_iterator(item_ptr(size())); }
306265

307-
reverse_iterator rbegin() { return reverse_iterator(item_ptr(size() - 1)); }
308-
const_reverse_iterator rbegin() const { return const_reverse_iterator(item_ptr(size() - 1)); }
309-
reverse_iterator rend() { return reverse_iterator(item_ptr(-1)); }
310-
const_reverse_iterator rend() const { return const_reverse_iterator(item_ptr(-1)); }
311-
312266
size_t capacity() const {
313267
if (is_direct()) {
314268
return N;

src/test/prevector_tests.cpp

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2015-2022 The Bitcoin Core developers
1+
// Copyright (c) 2015-present The Bitcoin Core developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

@@ -15,8 +15,9 @@
1515

1616
BOOST_FIXTURE_TEST_SUITE(prevector_tests, TestingSetup)
1717

18-
template<unsigned int N, typename T>
19-
class prevector_tester {
18+
template <unsigned int N, typename T>
19+
class prevector_tester
20+
{
2021
typedef std::vector<T> realtype;
2122
realtype real_vector;
2223
realtype real_vector_alt;
@@ -31,36 +32,37 @@ class prevector_tester {
3132

3233

3334
template <typename A, typename B>
34-
void local_check_equal(A a, B b)
35-
{
36-
local_check(a == b);
37-
}
35+
void local_check_equal(A a, B b)
36+
{
37+
local_check(a == b);
38+
}
3839
void local_check(bool b)
3940
{
4041
passed &= b;
4142
}
42-
void test() {
43+
void test()
44+
{
4345
const pretype& const_pre_vector = pre_vector;
4446
local_check_equal(real_vector.size(), pre_vector.size());
4547
local_check_equal(real_vector.empty(), pre_vector.empty());
4648
for (Size s = 0; s < real_vector.size(); s++) {
47-
local_check(real_vector[s] == pre_vector[s]);
48-
local_check(&(pre_vector[s]) == &(pre_vector.begin()[s]));
49-
local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s));
50-
local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
49+
local_check(real_vector[s] == pre_vector[s]);
50+
local_check(&(pre_vector[s]) == &(pre_vector.begin()[s]));
51+
local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s));
52+
local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
5153
}
5254
// local_check(realtype(pre_vector) == real_vector);
5355
local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
5456
local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
5557
size_t pos = 0;
5658
for (const T& v : pre_vector) {
57-
local_check(v == real_vector[pos++]);
59+
local_check(v == real_vector[pos++]);
5860
}
5961
for (const T& v : pre_vector | std::views::reverse) {
6062
local_check(v == real_vector[--pos]);
6163
}
6264
for (const T& v : const_pre_vector) {
63-
local_check(v == real_vector[pos++]);
65+
local_check(v == real_vector[pos++]);
6466
}
6567
for (const T& v : const_pre_vector | std::views::reverse) {
6668
local_check(v == real_vector[--pos]);
@@ -76,90 +78,105 @@ class prevector_tester {
7678
}
7779

7880
public:
79-
void resize(Size s) {
81+
void resize(Size s)
82+
{
8083
real_vector.resize(s);
8184
local_check_equal(real_vector.size(), s);
8285
pre_vector.resize(s);
8386
local_check_equal(pre_vector.size(), s);
8487
test();
8588
}
8689

87-
void reserve(Size s) {
90+
void reserve(Size s)
91+
{
8892
real_vector.reserve(s);
8993
local_check(real_vector.capacity() >= s);
9094
pre_vector.reserve(s);
9195
local_check(pre_vector.capacity() >= s);
9296
test();
9397
}
9498

95-
void insert(Size position, const T& value) {
99+
void insert(Size position, const T& value)
100+
{
96101
real_vector.insert(real_vector.begin() + position, value);
97102
pre_vector.insert(pre_vector.begin() + position, value);
98103
test();
99104
}
100105

101-
void insert(Size position, Size count, const T& value) {
106+
void insert(Size position, Size count, const T& value)
107+
{
102108
real_vector.insert(real_vector.begin() + position, count, value);
103109
pre_vector.insert(pre_vector.begin() + position, count, value);
104110
test();
105111
}
106112

107-
template<typename I>
108-
void insert_range(Size position, I first, I last) {
113+
template <typename I>
114+
void insert_range(Size position, I first, I last)
115+
{
109116
real_vector.insert(real_vector.begin() + position, first, last);
110117
pre_vector.insert(pre_vector.begin() + position, first, last);
111118
test();
112119
}
113120

114-
void erase(Size position) {
121+
void erase(Size position)
122+
{
115123
real_vector.erase(real_vector.begin() + position);
116124
pre_vector.erase(pre_vector.begin() + position);
117125
test();
118126
}
119127

120-
void erase(Size first, Size last) {
128+
void erase(Size first, Size last)
129+
{
121130
real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
122131
pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
123132
test();
124133
}
125134

126-
void update(Size pos, const T& value) {
135+
void update(Size pos, const T& value)
136+
{
127137
real_vector[pos] = value;
128138
pre_vector[pos] = value;
129139
test();
130140
}
131141

132-
void push_back(const T& value) {
142+
void push_back(const T& value)
143+
{
133144
real_vector.push_back(value);
134145
pre_vector.push_back(value);
135146
test();
136147
}
137148

138-
void pop_back() {
149+
void pop_back()
150+
{
139151
real_vector.pop_back();
140152
pre_vector.pop_back();
141153
test();
142154
}
143155

144-
void clear() {
156+
void clear()
157+
{
145158
real_vector.clear();
146159
pre_vector.clear();
147160
}
148161

149-
void assign(Size n, const T& value) {
162+
void assign(Size n, const T& value)
163+
{
150164
real_vector.assign(n, value);
151165
pre_vector.assign(n, value);
152166
}
153167

154-
Size size() const {
168+
Size size() const
169+
{
155170
return real_vector.size();
156171
}
157172

158-
Size capacity() const {
173+
Size capacity() const
174+
{
159175
return pre_vector.capacity();
160176
}
161177

162-
void shrink_to_fit() {
178+
void shrink_to_fit()
179+
{
163180
pre_vector.shrink_to_fit();
164181
test();
165182
}
@@ -171,19 +188,22 @@ class prevector_tester {
171188
test();
172189
}
173190

174-
void move() {
191+
void move()
192+
{
175193
real_vector = std::move(real_vector_alt);
176194
real_vector_alt.clear();
177195
pre_vector = std::move(pre_vector_alt);
178196
pre_vector_alt.clear();
179197
}
180198

181-
void copy() {
199+
void copy()
200+
{
182201
real_vector = real_vector_alt;
183202
pre_vector = pre_vector_alt;
184203
}
185204

186-
void resize_uninitialized(realtype values) {
205+
void resize_uninitialized(realtype values)
206+
{
187207
size_t r = values.size();
188208
size_t s = real_vector.size() / 2;
189209
if (real_vector.capacity() < s + r) {
@@ -203,11 +223,13 @@ class prevector_tester {
203223
test();
204224
}
205225

206-
~prevector_tester() {
226+
~prevector_tester()
227+
{
207228
BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString());
208229
}
209230

210-
prevector_tester(FastRandomContext& rng) {
231+
prevector_tester(FastRandomContext& rng)
232+
{
211233
rand_seed = rng.rand256();
212234
rng.Reseed(rand_seed);
213235
}

test/sanitizer_suppressions/ubsan

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,13 @@ unsigned-integer-overflow:DecompressAmount
5454
unsigned-integer-overflow:crypto/
5555
unsigned-integer-overflow:MurmurHash3
5656
unsigned-integer-overflow:TxConfirmStats::EstimateMedianVal
57-
unsigned-integer-overflow:prevector.h
5857
unsigned-integer-overflow:InsecureRandomContext::rand64
5958
unsigned-integer-overflow:InsecureRandomContext::SplitMix64
6059
unsigned-integer-overflow:bitset_detail::PopCount
6160
implicit-integer-sign-change:SetStdinEcho
6261
implicit-integer-sign-change:compressor.h
6362
implicit-integer-sign-change:crypto/
6463
implicit-integer-sign-change:TxConfirmStats::removeTx
65-
implicit-integer-sign-change:prevector.h
6664
implicit-integer-sign-change:verify_flags
6765
implicit-integer-sign-change:EvalScript
6866
implicit-integer-sign-change:serialize.h

0 commit comments

Comments
 (0)