From 0687fa573921084b4e045c3aaa087cc042f30475 Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Sat, 22 Jun 2024 06:29:36 -0300 Subject: [PATCH] add target for addrv2 --- Makefile | 2 +- btcd_lib/wrapper.go | 20 ++++++++++++++ fuzzer.cpp | 3 +++ rust_bitcoin_lib/rust_bitcoin_lib.h | 5 ++-- rust_bitcoin_lib/src/lib.rs | 17 ++++++++++++ targets/addrv2.cpp | 42 +++++++++++++++++++++++++++++ targets/addrv2.h | 7 +++++ 7 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 targets/addrv2.cpp create mode 100644 targets/addrv2.h diff --git a/Makefile b/Makefile index c78726b..598a3bb 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CXX = clang++ CC = clang -SOURCES := targets/script.cpp targets/psbt.cpp targets/bech32.cpp targets/tx_des.cpp targets/miniscript_string.cpp targets/block_des.cpp targets/prefilledtransaction.cpp +SOURCES := targets/addrv2.cpp targets/script.cpp targets/psbt.cpp targets/bech32.cpp targets/tx_des.cpp targets/miniscript_string.cpp targets/block_des.cpp targets/prefilledtransaction.cpp INCLUDES = dependencies/ dependencies/bitcoin/src/ dependencies/bitcoin/src/secp256k1/include LIB_DIR = dependencies/bitcoin/src/ dependencies/bitcoin/src/.libs dependencies/bitcoin/src/secp256k1/.libs rust_bitcoin_lib/target/debug btcd_lib OBJS := $(patsubst %.cpp, build/%.o, $(SOURCES)) diff --git a/btcd_lib/wrapper.go b/btcd_lib/wrapper.go index ea24467..dfb4da9 100644 --- a/btcd_lib/wrapper.go +++ b/btcd_lib/wrapper.go @@ -2,11 +2,13 @@ package main import "C" import ( + "bytes" "unsafe" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/bech32" + "github.com/btcsuite/btcd/wire" ) //export go_btcd_des_block @@ -50,6 +52,24 @@ func go_btcd_bech32(cinput *C.uchar, len C.int) *C.char { return C.CString("") } +//export go_btcd_addrv2 +func go_btcd_addrv2(cinput *C.uchar, datalen C.int, count *C.ulonglong) bool { + data := C.GoBytes(unsafe.Pointer(cinput), datalen) + r := bytes.NewReader(data) + m := &wire.MsgAddrV2{} + err := m.BtcDecode(r, 0, 0) + + actual_count := 0 + for i := 0; i < len(m.AddrList); i++ { + if m.AddrList[i].Addr != nil { + actual_count++ + } + } + *count = C.ulonglong(actual_count) + + return err == nil +} + func main() { } diff --git a/fuzzer.cpp b/fuzzer.cpp index f72f88b..a82ead0 100644 --- a/fuzzer.cpp +++ b/fuzzer.cpp @@ -13,6 +13,7 @@ #include "targets/bech32.h" #include "targets/psbt.h" #include "targets/script.h" +#include "targets/addrv2.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider provider(data, size); @@ -34,6 +35,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { Psbt(provider); } else if (target == "script") { Script(provider); + } else if (target == "addrv2") { + Addrv2(provider); } return 0; // Values other than 0 and -1 are reserved for future use. diff --git a/rust_bitcoin_lib/rust_bitcoin_lib.h b/rust_bitcoin_lib/rust_bitcoin_lib.h index a786782..3e478d2 100644 --- a/rust_bitcoin_lib/rust_bitcoin_lib.h +++ b/rust_bitcoin_lib/rust_bitcoin_lib.h @@ -1,8 +1,9 @@ #include extern bool rust_miniscript_from_str(const char* miniscript_str); -extern bool rust_bitcoin_script(const char* miniscript_str); -extern char* rust_bitcoin_psbt(const char* miniscript_str); +extern bool rust_bitcoin_script(const uint8_t *data, size_t len); +extern char* rust_bitcoin_psbt(const uint8_t *data, size_t len); extern char* rust_miniscript_from_str_check_key(const char* miniscript_str); extern char* rust_bitcoin_des_block(const uint8_t *data, size_t len); extern char* rust_bitcoin_prefilledtransaction(const uint8_t *data, size_t len); +extern bool rust_bitcoin_addrv2(uint8_t *data, size_t len, uint64_t *count); diff --git a/rust_bitcoin_lib/src/lib.rs b/rust_bitcoin_lib/src/lib.rs index 85d4247..361c0aa 100644 --- a/rust_bitcoin_lib/src/lib.rs +++ b/rust_bitcoin_lib/src/lib.rs @@ -118,6 +118,23 @@ pub unsafe extern "C" fn rust_bitcoin_script(data: *const u8, len: usize) -> boo } } +#[no_mangle] +pub unsafe extern "C" fn rust_bitcoin_addrv2(data: *const u8, len: usize, actual_count: *mut u64) -> bool { + // Safety: Ensure that the data pointer is valid for the given length + let data_slice = slice::from_raw_parts(data, len); + + let addr: Result<(Vec, usize), _> = encode::deserialize_partial(data_slice); + match addr { + Err(_) => { + false + }, + Ok(vec_addr) => { + *actual_count = vec_addr.0.len() as u64; + return true + } + } +} + #[no_mangle] pub unsafe extern "C" fn rust_miniscript_from_str_check_key(input: *const c_char) -> *mut c_char { let Ok(desc) = c_str_to_str(input) else { diff --git a/targets/addrv2.cpp b/targets/addrv2.cpp new file mode 100644 index 0000000..8bf08d1 --- /dev/null +++ b/targets/addrv2.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +#include "addrv2.h" +#include "bitcoin/src/protocol.h" +#include "bitcoin/src/streams.h" + +extern "C" bool rust_bitcoin_addrv2(uint8_t *data, size_t len, uint64_t *count); +extern "C" bool go_btcd_addrv2(uint8_t *data, size_t len, uint64_t *count); + +std::optional Core(Span buffer) +{ + std::vector addrs; + DataStream ds{buffer}; + try { + ds >> CAddress::V2_NETWORK(addrs); + if (addrs.size() > 1000) return std::nullopt; + } catch (const std::ios_base::failure&) { + return std::nullopt; + } + + return addrs.size(); +} + +void Addrv2(FuzzedDataProvider& provider) +{ + std::vector buffer{provider.ConsumeRemainingBytes()}; + uint64_t count_rust = 0, count_btcd = 0; + bool rust_bitcoin{rust_bitcoin_addrv2(buffer.data(), buffer.size(), &count_rust)}; + bool btcd{go_btcd_addrv2(buffer.data(), buffer.size(), &count_btcd)}; + std::optional core{Core(buffer)}; + assert(core.has_value() == rust_bitcoin); + assert(core.has_value() == btcd); + + if (core.has_value()) { + assert(*core == count_rust); + assert(*core >= count_btcd); + } +} \ No newline at end of file diff --git a/targets/addrv2.h b/targets/addrv2.h new file mode 100644 index 0000000..b7b061d --- /dev/null +++ b/targets/addrv2.h @@ -0,0 +1,7 @@ +#ifndef NET_ADDRESS_H +#define NET_ADDRESS_H + +#include + +void Addrv2(FuzzedDataProvider& provider); +#endif \ No newline at end of file