Skip to content

Commit 561915f

Browse files
committed
Merge bitcoin/bitcoin#27978: refactor: Drop unsafe AsBytePtr function
7c85361 refactor: Drop unsafe AsBytePtr function (Ryan Ofsky) Pull request description: Replace calls to `AsBytePtr` with calls to `AsBytes` or `reinterpret_cast`. `AsBytePtr` is just a wrapper around `reinterpret_cast`. It accepts any type of pointer as an argument and uses `reinterpret_cast` to cast the argument to a `std::byte` pointer. Despite taking any type of pointer as an argument, it is not useful to call `AsBytePtr` on most types of pointers, because byte representations of most types will be platform specific or undefined. Also, because it is named similarly to the `AsBytes` function, `AsBytePtr` looks safer than it actually is. Both `AsBytes` and `AsBytePtr` call reinterpret_cast internally and may be unsafe to use with certain types, but AsBytes at least has some type checking and can only be called on `Span` objects, while `AsBytePtr` can be called on any pointer argument. The change was motivated by discussion on #27973 and #27927 and is compatible with those PRs ACKs for top commit: jonatack: re-ACK 7c85361 sipa: utACK 7c85361 achow101: ACK 7c85361 Tree-SHA512: 200d858b1d4d579f081a7f9a14d488a99713b4918b4564ac3dd5c18578d927dbd6426e62e02f49f04a3fa73ca02ff7109c495cb0b92bec43c27d9b74e2f95757
2 parents c6287fa + 7c85361 commit 561915f

File tree

5 files changed

+24
-25
lines changed

5 files changed

+24
-25
lines changed

src/bench/ellswift.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ static void EllSwiftCreate(benchmark::Bench& bench)
1717
uint256 entropy = GetRandHash();
1818

1919
bench.batch(1).unit("pubkey").run([&] {
20-
auto ret = key.EllSwiftCreate(AsBytes(Span{entropy}));
20+
auto ret = key.EllSwiftCreate(MakeByteSpan(entropy));
2121
/* Use the first 32 bytes of the ellswift encoded public key as next private key. */
2222
key.Set(UCharCast(ret.data()), UCharCast(ret.data()) + 32, true);
2323
assert(key.IsValid());
2424
/* Use the last 32 bytes of the ellswift encoded public key as next entropy. */
25-
std::copy(ret.begin() + 32, ret.begin() + 64, AsBytePtr(entropy.data()));
25+
std::copy(ret.begin() + 32, ret.begin() + 64, MakeWritableByteSpan(entropy).begin());
2626
});
2727

2828
ECC_Stop();

src/serialize.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,10 @@ struct CustomUintFormatter
473473
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
474474
if (BigEndian) {
475475
uint64_t raw = htobe64(v);
476-
s.write({AsBytePtr(&raw) + 8 - Bytes, Bytes});
476+
s.write(AsBytes(Span{&raw, 1}).last(Bytes));
477477
} else {
478478
uint64_t raw = htole64(v);
479-
s.write({AsBytePtr(&raw), Bytes});
479+
s.write(AsBytes(Span{&raw, 1}).first(Bytes));
480480
}
481481
}
482482

@@ -486,10 +486,10 @@ struct CustomUintFormatter
486486
static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
487487
uint64_t raw = 0;
488488
if (BigEndian) {
489-
s.read({AsBytePtr(&raw) + 8 - Bytes, Bytes});
489+
s.read(AsWritableBytes(Span{&raw, 1}).last(Bytes));
490490
v = static_cast<I>(be64toh(raw));
491491
} else {
492-
s.read({AsBytePtr(&raw), Bytes});
492+
s.read(AsWritableBytes(Span{&raw, 1}).first(Bytes));
493493
v = static_cast<I>(le64toh(raw));
494494
}
495495
}

src/span.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -243,21 +243,16 @@ T& SpanPopBack(Span<T>& span)
243243
return back;
244244
}
245245

246-
//! Convert a data pointer to a std::byte data pointer.
247-
//! Where possible, please use the safer AsBytes helpers.
248-
inline const std::byte* AsBytePtr(const void* data) { return reinterpret_cast<const std::byte*>(data); }
249-
inline std::byte* AsBytePtr(void* data) { return reinterpret_cast<std::byte*>(data); }
250-
251246
// From C++20 as_bytes and as_writeable_bytes
252247
template <typename T>
253248
Span<const std::byte> AsBytes(Span<T> s) noexcept
254249
{
255-
return {AsBytePtr(s.data()), s.size_bytes()};
250+
return {reinterpret_cast<const std::byte*>(s.data()), s.size_bytes()};
256251
}
257252
template <typename T>
258253
Span<std::byte> AsWritableBytes(Span<T> s) noexcept
259254
{
260-
return {AsBytePtr(s.data()), s.size_bytes()};
255+
return {reinterpret_cast<std::byte*>(s.data()), s.size_bytes()};
261256
}
262257

263258
template <typename V>

src/wallet/bdb.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131

3232
namespace wallet {
3333
namespace {
34+
Span<const std::byte> SpanFromDbt(const SafeDbt& dbt)
35+
{
36+
return {reinterpret_cast<const std::byte*>(dbt.get_data()), dbt.get_size()};
37+
}
3438

3539
//! Make sure database has a unique fileid within the environment. If it
3640
//! doesn't, throw an error. BDB caches do not work properly when more than one
@@ -702,7 +706,7 @@ DatabaseCursor::Status BerkeleyCursor::Next(DataStream& ssKey, DataStream& ssVal
702706
return Status::FAIL;
703707
}
704708

705-
Span<const std::byte> raw_key = {AsBytePtr(datKey.get_data()), datKey.get_size()};
709+
Span<const std::byte> raw_key = SpanFromDbt(datKey);
706710
if (!m_key_prefix.empty() && std::mismatch(raw_key.begin(), raw_key.end(), m_key_prefix.begin(), m_key_prefix.end()).second != m_key_prefix.end()) {
707711
return Status::DONE;
708712
}
@@ -711,7 +715,7 @@ DatabaseCursor::Status BerkeleyCursor::Next(DataStream& ssKey, DataStream& ssVal
711715
ssKey.clear();
712716
ssKey.write(raw_key);
713717
ssValue.clear();
714-
ssValue.write({AsBytePtr(datValue.get_data()), datValue.get_size()});
718+
ssValue.write(SpanFromDbt(datValue));
715719
return Status::MORE;
716720
}
717721

@@ -796,7 +800,7 @@ bool BerkeleyBatch::ReadKey(DataStream&& key, DataStream& value)
796800
int ret = pdb->get(activeTxn, datKey, datValue, 0);
797801
if (ret == 0 && datValue.get_data() != nullptr) {
798802
value.clear();
799-
value.write({AsBytePtr(datValue.get_data()), datValue.get_size()});
803+
value.write(SpanFromDbt(datValue));
800804
return true;
801805
}
802806
return false;

src/wallet/sqlite.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
namespace wallet {
2525
static constexpr int32_t WALLET_SCHEMA_VERSION = 0;
2626

27+
static Span<const std::byte> SpanFromBlob(sqlite3_stmt* stmt, int col)
28+
{
29+
return {reinterpret_cast<const std::byte*>(sqlite3_column_blob(stmt, col)),
30+
static_cast<size_t>(sqlite3_column_bytes(stmt, col))};
31+
}
32+
2733
static void ErrorLogCallback(void* arg, int code, const char* msg)
2834
{
2935
// From sqlite3_config() documentation for the SQLITE_CONFIG_LOG option:
@@ -434,10 +440,8 @@ bool SQLiteBatch::ReadKey(DataStream&& key, DataStream& value)
434440
return false;
435441
}
436442
// Leftmost column in result is index 0
437-
const std::byte* data{AsBytePtr(sqlite3_column_blob(m_read_stmt, 0))};
438-
size_t data_size(sqlite3_column_bytes(m_read_stmt, 0));
439443
value.clear();
440-
value.write({data, data_size});
444+
value.write(SpanFromBlob(m_read_stmt, 0));
441445

442446
sqlite3_clear_bindings(m_read_stmt);
443447
sqlite3_reset(m_read_stmt);
@@ -527,12 +531,8 @@ DatabaseCursor::Status SQLiteCursor::Next(DataStream& key, DataStream& value)
527531
value.clear();
528532

529533
// Leftmost column in result is index 0
530-
const std::byte* key_data{AsBytePtr(sqlite3_column_blob(m_cursor_stmt, 0))};
531-
size_t key_data_size(sqlite3_column_bytes(m_cursor_stmt, 0));
532-
key.write({key_data, key_data_size});
533-
const std::byte* value_data{AsBytePtr(sqlite3_column_blob(m_cursor_stmt, 1))};
534-
size_t value_data_size(sqlite3_column_bytes(m_cursor_stmt, 1));
535-
value.write({value_data, value_data_size});
534+
key.write(SpanFromBlob(m_cursor_stmt, 0));
535+
value.write(SpanFromBlob(m_cursor_stmt, 1));
536536
return Status::MORE;
537537
}
538538

0 commit comments

Comments
 (0)