Skip to content

Commit 28d5074

Browse files
committed
Merge bitcoin/bitcoin#23253: bitcoin-tx: Reject non-integral and out of range int strings
fa6f29d bitcoin-tx: Reject non-integral and out of range multisig numbers (MarcoFalke) fafab8e bitcoin-tx: Reject non-integral and out of range sequence ids (MarcoFalke) fa53d3d test: Check that bitcoin-tx accepts whitespace around sequence id and multisig numbers (MarcoFalke) Pull request description: Seems odd to silently accept arbitrary strings that don't even represent integral values. Fix that. ACKs for top commit: practicalswift: cr ACK fa6f29d laanwj: Code review ACK fa6f29d Empact: Code review ACK bitcoin/bitcoin@fa6f29d promag: Code review ACK fa6f29d. Tree-SHA512: e31f7f21fe55ac069e755557bdbcae8d5d29e20ff82e441ebdfc65153e3a31a4edd46ad3e6dea5190ecbd1b8ea5a8f94daa5d59a3b7558e46e794e30db0e6c79
2 parents a9f6428 + fa6f29d commit 28d5074

File tree

3 files changed

+61
-7
lines changed

3 files changed

+61
-7
lines changed

src/bitcoin-tx.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,16 @@ static void MutateTxRBFOptIn(CMutableTransaction& tx, const std::string& strInId
235235
}
236236
}
237237

238+
template <typename T>
239+
static T TrimAndParse(const std::string& int_str, const std::string& err)
240+
{
241+
const auto parsed{ToIntegral<T>(TrimString(int_str))};
242+
if (!parsed.has_value()) {
243+
throw std::runtime_error(err + " '" + int_str + "'");
244+
}
245+
return parsed.value();
246+
}
247+
238248
static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInput)
239249
{
240250
std::vector<std::string> vStrInputParts;
@@ -261,8 +271,9 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
261271

262272
// extract the optional sequence number
263273
uint32_t nSequenceIn = CTxIn::SEQUENCE_FINAL;
264-
if (vStrInputParts.size() > 2)
265-
nSequenceIn = std::stoul(vStrInputParts[2]);
274+
if (vStrInputParts.size() > 2) {
275+
nSequenceIn = TrimAndParse<uint32_t>(vStrInputParts.at(2), "invalid TX sequence id");
276+
}
266277

267278
// append to transaction input list
268279
CTxIn txin(txid, vout, CScript(), nSequenceIn);
@@ -352,10 +363,10 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
352363
CAmount value = ExtractAndValidateValue(vStrInputParts[0]);
353364

354365
// Extract REQUIRED
355-
uint32_t required = stoul(vStrInputParts[1]);
366+
const uint32_t required{TrimAndParse<uint32_t>(vStrInputParts.at(1), "invalid multisig required number")};
356367

357368
// Extract NUMKEYS
358-
uint32_t numkeys = stoul(vStrInputParts[2]);
369+
const uint32_t numkeys{TrimAndParse<uint32_t>(vStrInputParts.at(2), "invalid multisig total number")};
359370

360371
// Validate there are the correct number of pubkeys
361372
if (vStrInputParts.size() < numkeys + 3)

test/lint/lint-locale-dependence.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ export LC_ALL=C
4141
# independent ToIntegral<T>(...) or the ParseInt*() functions.
4242
# TODO: Reduce KNOWN_VIOLATIONS by replacing uses of locale dependent snprintf with strprintf.
4343
KNOWN_VIOLATIONS=(
44-
"src/bitcoin-tx.cpp.*stoul"
4544
"src/dbwrapper.cpp:.*vsnprintf"
4645
"src/test/dbwrapper_tests.cpp:.*snprintf"
4746
"src/test/fuzz/locale.cpp"

test/util/data/bitcoin-util-test.json

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,30 @@
515515
"output_cmp": "txcreatedata2.json",
516516
"description": "Creates a new transaction with one input, one address output and one data (zero value) output (output in json)"
517517
},
518+
{ "exec": "./bitcoin-tx",
519+
"args":
520+
["-create",
521+
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:11aa"],
522+
"return_code": 1,
523+
"error_txt": "error: invalid TX sequence id '11aa'",
524+
"description": "Try to parse a sequence number outside the allowed range"
525+
},
526+
{ "exec": "./bitcoin-tx",
527+
"args":
528+
["-create",
529+
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:-1"],
530+
"return_code": 1,
531+
"error_txt": "error: invalid TX sequence id '-1'",
532+
"description": "Try to parse a sequence number outside the allowed range"
533+
},
534+
{ "exec": "./bitcoin-tx",
535+
"args":
536+
["-create",
537+
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0:4294967296"],
538+
"return_code": 1,
539+
"error_txt": "error: invalid TX sequence id '4294967296'",
540+
"description": "Try to parse a sequence number outside the allowed range"
541+
},
518542
{ "exec": "./bitcoin-tx",
519543
"args":
520544
["-create",
@@ -523,6 +547,14 @@
523547
"output_cmp": "txcreatedata_seq0.hex",
524548
"description": "Creates a new transaction with one input with sequence number and one address output"
525549
},
550+
{ "exec": "./bitcoin-tx",
551+
"args":
552+
["-create",
553+
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0: 4294967293 ",
554+
"outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o"],
555+
"output_cmp": "txcreatedata_seq0.hex",
556+
"description": "Creates a new transaction with one input with sequence number (+whitespace) and one address output"
557+
},
526558
{ "exec": "./bitcoin-tx",
527559
"args":
528560
["-json",
@@ -547,15 +579,27 @@
547579
"output_cmp": "txcreatedata_seq1.json",
548580
"description": "Adds a new input with sequence number to a transaction (output in json)"
549581
},
582+
{ "exec": "./bitcoin-tx",
583+
"args": ["-create", "outmultisig=1:-2:3:02a5:021:02df", "nversion=1"],
584+
"return_code": 1,
585+
"error_txt": "error: invalid multisig required number '-2'",
586+
"description": "Try to parse a multisig number outside the allowed range"
587+
},
588+
{ "exec": "./bitcoin-tx",
589+
"args": ["-create", "outmultisig=1:2:3a:02a5:021:02df", "nversion=1"],
590+
"return_code": 1,
591+
"error_txt": "error: invalid multisig total number '3a'",
592+
"description": "Try to parse a multisig number outside the allowed range"
593+
},
550594
{ "exec": "./bitcoin-tx",
551595
"args": ["-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485", "nversion=1"],
552596
"output_cmp": "txcreatemultisig1.hex",
553597
"description": "Creates a new transaction with a single 2-of-3 multisig output"
554598
},
555599
{ "exec": "./bitcoin-tx",
556-
"args": ["-json", "-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485", "nversion=1"],
600+
"args": ["-json", "-create", "outmultisig=1: 2 : 3 :02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485", "nversion=1"],
557601
"output_cmp": "txcreatemultisig1.json",
558-
"description": "Creates a new transaction with a single 2-of-3 multisig output (output in json)"
602+
"description": "Creates a new transaction with a single 2-of-3 multisig output (with whitespace, output in json)"
559603
},
560604
{ "exec": "./bitcoin-tx",
561605
"args": ["-create", "outmultisig=1:2:3:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397:021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d:02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485:S", "nversion=1"],

0 commit comments

Comments
 (0)