Change Parse descriptor argument to string_view
What changed, and why it matters
This commit fixes a minor developer-facing bug in how Bitcoin Core parses text-based wallet descriptors. A recent code change had made the parser accept raw character spans, which accidentally included the hidden null terminator at the end of C++ string literals. That caused the parser to reject valid descriptors with a misleading 'Invalid characters in payload' error. The fix switches the public API to use std::string_view, which does not include the trailing null byte, and adds a regression test. It is not a consensus or network security issue.
No urgent action required. Treat as a normal code-quality/regression fix. Reviewers should verify the new test passes and that no other callers rely on the removed std::span<const char> signature.
Security signals we found
API usability fix that prevents misleading parse failures
Regression test added for null-byte edge case
No consensus, cryptography, or network layer changes
Evidence from the diff
Commit b3bf18f0bac0ffe18206ee20642e11264ba0c99d changed Descriptor::Parse to take std::span
Changed components
src/script/descriptor.cppsrc/script/descriptor.hsrc/test/descriptor_tests.cppInspect captured patch +15 / −5
diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp
index a4294331..6363d176 100644
--- a/src/script/descriptor.cpp
+++ b/src/script/descriptor.cpp
@@ -2743,12 +2743,13 @@ bool CheckChecksum(std::span<const char>& sp, bool require_checksum, std::string
return true;
}
-std::vector<std::unique_ptr<Descriptor>> Parse(std::span<const char> descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum)
+std::vector<std::unique_ptr<Descriptor>> Parse(std::string_view descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum)
{
- if (!CheckChecksum(descriptor, require_checksum, error)) return {};
+ std::span<const char> sp{descriptor};
+ if (!CheckChecksum(sp, require_checksum, error)) return {};
uint32_t key_exp_index = 0;
- auto ret = ParseScript(key_exp_index, descriptor, ParseScriptContext::TOP, out, error);
- if (descriptor.empty() && !ret.empty()) {
+ auto ret = ParseScript(key_exp_index, sp, ParseScriptContext::TOP, out, error);
+ if (sp.empty() && !ret.empty()) {
std::vector<std::unique_ptr<Descriptor>> descs;
descs.reserve(ret.size());
for (auto& r : ret) {
diff --git a/src/script/descriptor.h b/src/script/descriptor.h
index 9a018300..a6744b92 100644
--- a/src/script/descriptor.h
+++ b/src/script/descriptor.h
@@ -175,7 +175,7 @@ struct Descriptor {
* If a parse error occurs, or the checksum is missing/invalid, or anything
* else is wrong, an empty vector is returned.
*/
-std::vector<std::unique_ptr<Descriptor>> Parse(std::span<const char> descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false);
+std::vector<std::unique_ptr<Descriptor>> Parse(std::string_view descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false);
/** Get the checksum for a `descriptor`.
*
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
index 098007c4..97f416dd 100644
--- a/src/test/descriptor_tests.cpp
+++ b/src/test/descriptor_tests.cpp
@@ -1262,4 +1262,13 @@ BOOST_AUTO_TEST_CASE(descriptor_test)
CheckUnparsable("tr(musig(tuus(oldepk(gg)ggggfgg)<,z(((((((((((((((((((((st)", "tr(musig(tuus(oldepk(gg)ggggfgg)<,z(((((((((((((((((((((st)","tr(): Too many ')' in musig() expression");
}
+BOOST_AUTO_TEST_CASE(descriptor_literal_null_byte)
+{
+ // Trailing '\0' string literal should be ignored.
+ FlatSigningProvider keys;
+ std::string err;
+ auto descs = Parse("pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)", keys, err, /*require_checksum=*/false);
+ BOOST_REQUIRE_MESSAGE(!descs.empty(), err);
+}
+
BOOST_AUTO_TEST_SUITE_END()
Why this scored 20/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.