Repository: bitcoin/bitcoin (language: cpp)

Issue:
psbt.h:896:51: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned long'
This needs a code change or suppression added:

```
$ UBSAN_OPTIONS="suppressions=$(pwd)/scratch/fuzz_gen/code/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1" FUZZ=partially_signed_transaction_deserialize /root/fuzz_dir/scratch/fuzz_gen/code/src/test/fuzz/fuzz /tmp/crash-e4a4fe6f63596cd582f208eea9be69b716f61165 
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3574901271
INFO: Loaded 1 modules   (322037 inline 8-bit counters): 322037 [0x555887da9f40, 0x555887df8935), 
INFO: Loaded 1 PC tables (322037 PCs): 322037 [0x555887df8938,0x5558882e2888), 
/root/fuzz_dir/scratch/fuzz_gen/code/src/test/fuzz/fuzz: Running 1 inputs 1 time(s) each.
Running: /tmp/crash-e4a4fe6f63596cd582f208eea9be69b716f61165
psbt.h:896:51: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'unsigned long'
    #0 0x555885271598 in void PSBTOutput::Unserialize<CDataStream>(CDataStream&) src/./psbt.h:896:51
    #1 0x555885233a4e in void Unserialize<CDataStream, PSBTOutput&>(CDataStream&, PSBTOutput&) src/./serialize.h:682:7
    #2 0x555885233a4e in CDataStream& CDataStream::operator>><PSBTOutput&>(PSBTOutput&) src/./streams.h:339:9
    #3 0x55588523024f in void PartiallySignedTransaction::Unserialize<CDataStream>(CDataStream&) src/./psbt.h:1191:15
    #4 0x55588522edee in void Unserialize<CDataStream, PartiallySignedTransaction&>(CDataStream&, PartiallySignedTransaction&) src/./serialize.h:682:7
    #5 0x55588522edee in CDataStream& CDataStream::operator>><PartiallySignedTransaction&>(PartiallySignedTransaction&) src/./streams.h:339:9
    #6 0x5558852067f5 in void (anonymous namespace)::DeserializeFromFuzzingInput<PartiallySignedTransaction>(Span<unsigned char const>, PartiallySignedTransaction&, std::optional<int>, int) src/./src/test/fuzz/deserialize.cpp:100:12
    #7 0x5558852067f5 in partially_signed_transaction_deserialize_fuzz_target(Span<unsigned char const>) src/./src/test/fuzz/deserialize.cpp:173:1
    #8 0x555885106682 in std::_Function_handler<void (Span<unsigned char const>), void (*)(Span<unsigned char const>)>::_M_invoke(std::_Any_data const&, Span<unsigned char const>&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/std_function.h:300:2
    #9 0x55588549ae5a in std::function<void (Span<unsigned char const>)>::operator()(Span<unsigned char const>) const /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/std_function.h:688:14
    #10 0x55588549aad6 in LLVMFuzzerTestOneInput src/./src/test/fuzz/fuzz.cpp:154:5
    #11 0x555885029372 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/root/fuzz_dir/scratch/fuzz_gen/code/src/test/fuzz/fuzz+0x141a372) (BuildId: 8e23fc37575bb16be5b418c47853b5da4e548abb)
    #12 0x5558850138d0 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/root/fuzz_dir/scratch/fuzz_gen/code/src/test/fuzz/fuzz+0x14048d0) (BuildId: 8e23fc37575bb16be5b418c47853b5da4e548abb)
    #13 0x555885019587 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/root/fuzz_dir/scratch/fuzz_gen/code/src/test/fuzz/fuzz+0x140a587) (BuildId: 8e23fc37575bb16be5b418c47853b5da4e548abb)
    #14 0x555885042342 in main (/root/fuzz_dir/scratch/fuzz_gen/code/src/test/fuzz/fuzz+0x1433342) (BuildId: 8e23fc37575bb16be5b418c47853b5da4e548abb)
    #15 0x7fa7994a3082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #16 0x55588500e1cd in _start (/root/fuzz_dir/scratch/fuzz_gen/code/src/test/fuzz/fuzz+0x13ff1cd) (BuildId: 8e23fc37575bb16be5b418c47853b5da4e548abb)

SUMMARY: UndefinedBehaviorSanitizer: unsigned-integer-overflow psbt.h:896:51 in 
```

```
$ base64 /tmp/crash-e4a4fe6f63596cd582f208eea9be69b716f61165 
rPcKGHBzYnT/AQA9AAAAAAF6AAGDEwEA+8QAAP9glCALb/ITYCf/BwABAR4AAAAAWAAAAAAAGHBz
YgEBTEtAIxPsMAEAAAn8/wABKwAH/ACOCcgAAAAF/AAAAPwEAAAAAAb8AAAAAWQAA/wAAAf8AI4J
yCQuAAf8AAIA/wgBAAf8AAAJyAAAACEH/AAAjQFkygAG/AAACSEAASsBKwAH/ACOCcgAAAAF/AAA
APwEAAAAAAb8AAAAAAAG/AArAAFkAAP8AAAH/ACOCQAAIQAG/AAA/wgBAAf8AAAJwgAAAAf8AAAw
AWTKAAb8AAABQA8AB/wAAAAJASsAB/wAjgnIAAAABfwAAAD8BAAAAAAG/AAAAAAAAAEG/ABkAAP8
AAAH/AAACcgAAAAH/AAANQFkygAG/AAAAUAPAAf8AAkhAAErAAf8AAAACfz/AAErAAf8jgkAAMgA
AAX8AAAA/AQAAAAABvwAAAAAAAb8AAABZAAD/AAAB/wAjgnIJi4AB/wAAgAAAAAG/AAA/wgAB/wA
ADABZMoABvwAAAFADwAH/AAJIQABKwAH/AAAAAn8/wABKwAH/ACOCcgAAAAF/AAAAPwEAAAAAAb8
AAAAAWQAA/wAAAf8AI4JyCYuAAf8AAIA/wgBAAf8AAAJyAAAAAf8AACNAWTKAAb8AAAJIQABKwEr
AAf8AI4JyAAAAAX8AAAA/AQAAAAABvwAAAAAAAb8AAABZAAD/AAAB/wAjgnIJi4AB/wAAgAAACEA
BvwAAP8IAQAH/AAACcIAAAAH/AAAMAFkygAG/AAAAUAPAAf8AAkhAPwAAAD8AAQAAAAG/AAAAAFk
AAP8AAAH/ACOCcgkLgAH/AACAP8IAQAH/AAACcgAAAAH/AAAjQFk/AAACcIAAAAH/AAAMAFkygAG
/AAAAUAPAAf8AAAACQErAAf8AI4JyAAAAAX8AAAA/AQAAAAABvwAAAAAAAABBvwAZAAD/AAAB/wA
AAnIAAAAB/wAADUBZMoABvwAAAFADwAH/AAJIQABKwAH/AAAAAn8/wABKwAH/ACOCcgAAAAF/AAA
APwEAAAAAAb8AAAAAAAG/AAAAWQAA/wAAAf8AI4JyCYuAAf8AAIAAAAABvwAAAAAAAAAAAAAAAAA
AAD/CAAH/AAAMAFkygAG/AAAAUAPAAf8AAkhAAErAAf8AAAACfz/AAErAAf8AI4JyAAAAAX8AAAA
/AQAAAAABvwAAAABZAAD/AAAB/wAjgnIJi4AA/wAAAf8AI4JyCQuAAf8AAIA/wgBAAf8AAAJyAAA
AAf8AACNQGTKAAb8AAAJIQABKwErAAf8AI4JyAAAAAX8AAAA/AQAAAAABvwAAAAAAAb8ACsAAWQA
A/wAAAf8AI4JAAAhAAb8AAD/CAEAB/wAAAnCAAAAB/wAADABZMoABvwAAAFADwAH/AAAAAkBKwAH
/ACOCcgAAAAF/AAAAPwEAAAAAAb8AAAAAAAAAQb8AGQAA/wAAAf8E2An/wcAAQEeAv0AAHAkA/kV
YI4A/wTEAAD/YJ4iIiIiIq4AAAAAAAA=



Discussion / hints:
What is the psbt that triggered this? The case that you posted doesn't look right.
Did you compile with the `integer` sanitizer?
Here are the steps to reproduce on a fresh install of Ubuntu:

```
    1  export DEBIAN_FRONTEND=noninteractive && apt update && apt install curl wget htop git vim ccache -y && git clone https://github.com/bitcoin/bitcoin.git bitcoin-core && cd bitcoin-core && apt install build-essential libtool autotools-dev automake pkg-config bsdmainutils python3-zmq     libevent-dev libboost-dev   clang llvm   -y   &&  ./autogen.sh
    2  ./configure CC=clang CXX='clang++'   --enable-fuzz --with-sanitizers=fuzzer,integer && make -j$(nproc)
    3  echo 'rPcKGHBzYnT/AQA9AAAAAAF6AAGDEwEA+8QAAP9glCALb/ITYCf/BwABAR4AAAAAWAAAAAAAGHBz
YgEBTEtAIxPsMAEAAAn8/wABKwAH/ACOCcgAAAAF/AAAAPwEAAAAAAb8AAAAAWQAA/wAAAf8AI4J
yCQuAAf8AAIA/wgBAAf8AAAJyAAAACEH/AAAjQFkygAG/AAACSEAASsBKwAH/ACOCcgAAAAF/AAA
APwEAAAAAAb8AAAAAAAG/AArAAFkAAP8AAAH/ACOCQAAIQAG/AAA/wgBAAf8AAAJwgAAAAf8AAAw
AWTKAAb8AAABQA8AB/wAAAAJASsAB/wAjgnIAAAABfwAAAD8BAAAAAAG/AAAAAAAAAEG/ABkAAP8
AAAH/AAACcgAAAAH/AAANQFkygAG/AAAAUAPAAf8AAkhAAErAAf8AAAACfz/AAErAAf8jgkAAMgA
AAX8AAAA/AQAAAAABvwAAAAAAAb8AAABZAAD/AAAB/wAjgnIJi4AB/wAAgAAAAAG/AAA/wgAB/wA
ADABZMoABvwAAAFADwAH/AAJIQABKwAH/AAAAAn8/wABKwAH/ACOCcgAAAAF/AAAAPwEAAAAAAb8
AAAAAWQAA/wAAAf8AI4JyCYuAAf8AAIA/wgBAAf8AAAJyAAAAAf8AACNAWTKAAb8AAAJIQABKwEr
AAf8AI4JyAAAAAX8AAAA/AQAAAAABvwAAAAAAAb8AAABZAAD/AAAB/wAjgnIJi4AB/wAAgAAACEA
BvwAAP8IAQAH/AAACcIAAAAH/AAAMAFkygAG/AAAAUAPAAf8AAkhAPwAAAD8AAQAAAAG/AAAAAFk
AAP8AAAH/ACOCcgkLgAH/AACAP8IAQAH/AAACcgAAAAH/AAAjQFk/AAACcIAAAAH/AAAMAFkygAG
/AAAAUAPAAf8AAAACQErAAf8AI4JyAAAAAX8AAAA/AQAAAAABvwAAAAAAAABBvwAZAAD/AAAB/wA
AAnIAAAAB/wAADUBZMoABvwAAAFADwAH/AAJIQABKwAH/AAAAAn8/wABKwAH/ACOCcgAAAAF/AAA
APwEAAAAAAb8AAAAAAAG/AAAAWQAA/wAAAf8AI4JyCYuAAf8AAIAAAAABvwAAAAAAAAAAAAAAAAA
AAD/CAAH/AAAMAFkygAG/AAAAUAPAAf8AAkhAAErAAf8AAAACfz/AAErAAf8AI4JyAAAAAX8AAAA
/AQAAAAABvwAAAABZAAD/AAAB/wAjgnIJi4AA/wAAAf8AI4JyCQuAAf8AAIA/wgBAAf8AAAJyAAA
AAf8AACNQGTKAAb8AAAJIQABKwErAAf8AI4JyAAAAAX8AAAA/AQAAAAABvwAAAAAAAb8ACsAAWQA
A/wAAAf8AI4JAAAhAAb8AAD/CAEAB/wAAAnCAAAAB/wAADABZMoABvwAAAFADwAH/AAAAAkBKwAH
/ACOCcgAAAAF/AAAAPwEAAAAAAb8AAAAAAAAAQb8AGQAA/wAAAf8E2An/wcAAQEeAv0AAHAkA/kV
YI4A/wTEAAD/YJ4iIiIiIq4AAAAAAAA='|base64 --decode > /tmp/crash-1
    4  UBSAN_OPTIONS="suppressions=$(pwd)/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1" FUZZ=partially_signed_transaction_deserialize ./src/test/fuzz/fuzz /tmp/crash-1 
    5  history 


Fix patch:
diff --git a/src/psbt.h b/src/psbt.h
index c390bb67d3813..eef7d7dd3b233 100644
--- a/src/psbt.h
+++ b/src/psbt.h
@@ -893,6 +893,9 @@ struct PSBTOutput
                     s >> leaf_hashes;
                     size_t after_hashes = s.size();
                     size_t hashes_len = before_hashes - after_hashes;
+                    if (hashes_len > value_len) {
+                        throw std::ios_base::failure("Output Taproot BIP32 keypath has an invalid length");
+                    }
                     size_t origin_len = value_len - hashes_len;
                     m_tap_bip32_paths.emplace(xonly, std::make_pair(leaf_hashes, DeserializeKeyOrigin(s, origin_len)));
                     break;


Test patch: