From 5de2f97a0521fe75b47f9840141c4ace74656de9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C5=91rinc?= Date: Tue, 21 Apr 2026 11:56:49 +0200 Subject: [PATCH] dbwrapper: use `SpanReader` for iterator keys `CDBIterator::GetKey()` only deserializes the current LevelDB key once. `GetKeyImpl()` already exposes the current key as a contiguous borrowed byte span, and `GetKey()` creates a fresh local reader and only performs immediate forward reads before returning. Switch this path to `SpanReader` so the key bytes are read in place instead of being copied into a temporary `DataStream`. This keeps the same exception swallowing and `bool` return semantics while avoiding the extra allocation and copy. The preceding test locks down the subtle safety property that matters here: a failed decode must not consume the current iterator entry. Note that the same simplification does not apply to `GetValue()`, because that path deobfuscates the value bytes in place first and still needs an owning mutable buffer. --- src/dbwrapper.cpp | 2 ++ src/dbwrapper.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index eb222078b5e..50a58d5fe03 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -370,6 +370,8 @@ void CDBIterator::SeekImpl(std::span key) std::span CDBIterator::GetKeyImpl() const { + // The returned span borrows from the current iterator entry and is only + // valid until the iterator is advanced. return MakeByteSpan(m_impl_iter->iter->key()); } diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 2eee6c1c023..75ac5fdb05b 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -153,7 +153,7 @@ public: template bool GetKey(K& key) { try { - DataStream ssKey{GetKeyImpl()}; + SpanReader ssKey{GetKeyImpl()}; ssKey >> key; } catch (const std::exception&) { return false;