Skip to content

Commit 47cabbf

Browse files
committed
Merge rust-bitcoin#5492: Fix unreachable error bug during iteration of funding utxos
a5bd502 Fix unreachable error bug during iteration of funding utxos (Shing Him Ng) Pull request description: Found this while working on a psbt fuzz target: ``` INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 3835569058 INFO: Loaded 1 modules (61329 inline 8-bit counters): 61329 [0x100a2acf0, 0x100a39c81), INFO: Loaded 1 PC tables (61329 PCs): 61329 [0x100a39c88,0x100b29598), target/aarch64-apple-darwin/release/bitcoin_arbitrary_psbt: Running 1 inputs 1 time(s) each. Running: fuzz/artifacts/bitcoin_arbitrary_psbt/crash-ba0bb9c6187caa78cd865a232ef56ea1a690e25b thread '<unnamed>' (7096951) panicked at bitcoin/src/psbt/mod.rs:204:18: internal error: entered unreachable code note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ==48521== ERROR: libFuzzer: deadly signal #0 0x0001012893c4 in __sanitizer_print_stack_trace+0x28 (librustc-nightly_rt.asan.dylib:arm64+0x5d3c4) #1 0x0001007c8300 in fuzzer::PrintStackTrace()+0x30 (bitcoin_arbitrary_psbt:arm64+0x100354300) #2 0x0001007bc7e4 in fuzzer::Fuzzer::CrashCallback()+0x54 (bitcoin_arbitrary_psbt:arm64+0x1003487e4) #3 0x00019914f740 in _sigtramp+0x34 (libsystem_platform.dylib:arm64+0x3740) #4 0x000199145884 in pthread_kill+0x124 (libsystem_pthread.dylib:arm64+0x6884) #5 0x00019904a84c in abort+0x78 (libsystem_c.dylib:arm64+0x7984c) #6 0x0001008429c4 in _RNvNtNtNtCsk9AQ7OSayGk_3std3sys3pal4unix14abort_internal+0x8 (bitcoin_arbitrary_psbt:arm64+0x1003ce9c4) #7 0x000100842820 in _RNvNtCsk9AQ7OSayGk_3std7process5abort+0x8 (bitcoin_arbitrary_psbt:arm64+0x1003ce820) #8 0x00010083d9fc in _RNCNvCsaBYAWE6hvc2_13libfuzzer_sys10initialize0B3_+0xb8 (bitcoin_arbitrary_psbt:arm64+0x1003c99fc) #9 0x0001008174d4 in _RNvNtCsk9AQ7OSayGk_3std9panicking15panic_with_hook+0x264 (bitcoin_arbitrary_psbt:arm64+0x1003a34d4) #10 0x00010080b5b0 in _RNCNvNtCsk9AQ7OSayGk_3std9panicking13panic_handler0B5_+0x6c (bitcoin_arbitrary_psbt:arm64+0x1003975b0) #11 0x000100802f0c in _RINvNtNtCsk9AQ7OSayGk_3std3sys9backtrace26___rust_end_short_backtraceNCNvNtB6_9panicking13panic_handler0zEB6_+0x8 (bitcoin_arbitrary_psbt:arm64+0x10038ef0c) #12 0x00010080bb94 in _RNvCseYE12Li5r0M_7___rustc17rust_begin_unwind+0x1c (bitcoin_arbitrary_psbt:arm64+0x100397b94) #13 0x00010084311c in _RNvNtCsh0x4TIixgmZ_4core9panicking9panic_fmt+0x24 (bitcoin_arbitrary_psbt:arm64+0x1003cf11c) #14 0x0001008430f4 in _RNvNtCsh0x4TIixgmZ_4core9panicking5panic+0x10 (bitcoin_arbitrary_psbt:arm64+0x1003cf0f4) #15 0x00010056c670 in _RNvMNtCs9rLNVcx1A2L_7bitcoin4psbtNtB2_4Psbt39internal_extract_tx_with_fee_rate_limit+0x4e0 (bitcoin_arbitrary_psbt:arm64+0x1000f8670) #16 0x00010049ddd8 in _RNvNvCshHXwvrCOqYg_22bitcoin_arbitrary_psbt1__19___libfuzzer_sys_run arbitrary_psbt.rs:41 #17 0x0001004a545c in rust_fuzzer_test_input lib.rs:276 #18 0x0001007bad98 in _RINvNvNtCsk9AQ7OSayGk_3std9panicking12catch_unwind7do_callNCNvCsaBYAWE6hvc2_13libfuzzer_sys15test_input_wrap0lEBY_+0xc4 (bitcoin_arbitrary_psbt:arm64+0x100346d98) #19 0x0001007bba60 in __rust_try+0x18 (bitcoin_arbitrary_psbt:arm64+0x100347a60) #20 0x0001007ba698 in LLVMFuzzerTestOneInput+0x16c (bitcoin_arbitrary_psbt:arm64+0x100346698) #21 0x0001007be09c in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)+0x158 (bitcoin_arbitrary_psbt:arm64+0x10034a09c) #22 0x0001007d955c in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long)+0xd8 (bitcoin_arbitrary_psbt:arm64+0x10036555c) #23 0x0001007de1cc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long))+0x1b8c (bitcoin_arbitrary_psbt:arm64+0x10036a1cc) #24 0x0001007eab84 in main+0x24 (bitcoin_arbitrary_psbt:arm64+0x100376b84) #25 0x000198d7dd50 (<unknown module>) NOTE: libFuzzer has rudimentary signal handlers. Combine libFuzzer with AddressSanitizer or similar for better crash reports. SUMMARY: libFuzzer: deadly signal ──────────────────────────────────────────────────────────────────────────────── ``` I wasn't positive on if i should group it with `Error::MissingUtxo` and return `ExtractTxError::MissingInputAmount` ACKs for top commit: tcharding: ACK a5bd502 apoelstra: ACK a5bd502; successfully ran local tests Tree-SHA512: 0fcc7663a5a3458f1eb5a968e200928c5476dfcce9a765437bab5987294373ba8e919d8e606de06ee69acda2100ffb348907173d8c9ce7a4cc62efb5ad108f8b
2 parents df534c7 + a5bd502 commit 47cabbf

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

bitcoin/src/psbt/mod.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ impl Psbt {
191191
) -> Result<Transaction, ExtractTxError> {
192192
let fee = match self.fee() {
193193
Ok(fee) => fee,
194-
Err(Error::MissingUtxo) =>
194+
Err(Error::MissingUtxo) | Err(Error::PsbtUtxoOutOfbounds) =>
195195
return Err(ExtractTxError::MissingInputAmount { tx: self.internal_extract_tx() }),
196196
Err(Error::NegativeFee) => return Err(ExtractTxError::SendingTooMuch { psbt: self }),
197197
Err(Error::FeeOverflow) =>
@@ -2502,6 +2502,62 @@ mod tests {
25022502
}
25032503
}
25042504

2505+
#[test]
2506+
fn test_psbt_utxo_out_of_bounds() {
2507+
let prev_tx = Transaction {
2508+
version: transaction::Version::TWO,
2509+
lock_time: absolute::LockTime::ZERO,
2510+
inputs: vec![],
2511+
outputs: vec![
2512+
TxOut {
2513+
amount: Amount::default(),
2514+
script_pubkey: ScriptPubKeyBuf::new()
2515+
}
2516+
],
2517+
};
2518+
2519+
let unsigned_tx = Transaction {
2520+
version: transaction::Version::TWO,
2521+
lock_time: absolute::LockTime::ZERO,
2522+
inputs: vec![
2523+
TxIn {
2524+
previous_output: OutPoint {
2525+
txid: prev_tx.compute_txid(),
2526+
vout: 5, // This doesn't have a corresponding output
2527+
},
2528+
script_sig: ScriptSigBuf::new(),
2529+
sequence: Sequence::default(),
2530+
witness: Witness::new(),
2531+
}
2532+
],
2533+
outputs: vec![
2534+
TxOut {
2535+
amount: Amount::default(),
2536+
script_pubkey: ScriptPubKeyBuf::new(),
2537+
}
2538+
],
2539+
};
2540+
2541+
let psbt = Psbt {
2542+
unsigned_tx,
2543+
version: 0,
2544+
xpub: Default::default(),
2545+
proprietary: Default::default(),
2546+
unknown: Default::default(),
2547+
inputs: vec![
2548+
Input {
2549+
non_witness_utxo: Some(prev_tx),
2550+
witness_utxo: None,
2551+
..Default::default()
2552+
}
2553+
],
2554+
outputs: vec![Output::default()],
2555+
};
2556+
2557+
assert!(matches!(psbt.fee(), Err(Error::PsbtUtxoOutOfbounds)));
2558+
assert!(matches!(psbt.internal_extract_tx_with_fee_rate_limit(FeeRate::MAX), Err(ExtractTxError::MissingInputAmount { tx: _ })))
2559+
}
2560+
25052561
#[test]
25062562
#[cfg(all(feature = "rand", feature = "std"))]
25072563
fn hashmap_can_sign_taproot() {

0 commit comments

Comments
 (0)