Skip to content

Commit 7c85361

Browse files
ryanofskysipa
andcommitted
refactor: Drop unsafe AsBytePtr function
Replace calls to AsBytePtr with direct 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 implmentation-specific. 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. Co-authored-by: Pieter Wuille <[email protected]>
1 parent 7ee4121 commit 7c85361

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
@@ -472,10 +472,10 @@ struct CustomUintFormatter
472472
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
473473
if (BigEndian) {
474474
uint64_t raw = htobe64(v);
475-
s.write({AsBytePtr(&raw) + 8 - Bytes, Bytes});
475+
s.write(AsBytes(Span{&raw, 1}).last(Bytes));
476476
} else {
477477
uint64_t raw = htole64(v);
478-
s.write({AsBytePtr(&raw), Bytes});
478+
s.write(AsBytes(Span{&raw, 1}).first(Bytes));
479479
}
480480
}
481481

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

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)