Skip to content

Commit

Permalink
Check lengths after deserialization in cmpctblocks target
Browse files Browse the repository at this point in the history
  • Loading branch information
hax0kartik committed Jul 1, 2024
1 parent d03ef96 commit 603cc2a
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 12 deletions.
3 changes: 3 additions & 0 deletions fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "targets/psbt.h"
#include "targets/script.h"
#include "targets/addrv2.h"
#include "targets/cmpctblocks.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider provider(data, size);
Expand All @@ -37,6 +38,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
Script(provider);
} else if (target == "addrv2") {
Addrv2(provider);
} else if (target == "cmpctblocks") {
CmpctBlocks(provider);
}

return 0; // Values other than 0 and -1 are reserved for future use.
Expand Down
8 changes: 4 additions & 4 deletions rust_bitcoin_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,20 +137,20 @@ pub unsafe extern "C" fn rust_bitcoin_addrv2(data: *const u8, len: usize, actual
}

#[no_mangle]
pub unsafe extern "C" fn rust_bitcoin_cmpctblocks(data: *const u8, len: usize) -> *mut c_char {
pub unsafe extern "C" fn rust_bitcoin_cmpctblocks(data: *const u8, len: usize) -> i32 {
// Safety: Ensure that the data pointer is valid for the given length
let data_slice = slice::from_raw_parts(data, len);

let res = deserialize_partial::<HeaderAndShortIds>(data_slice);

match res {
Ok(_) => return str_to_c_string("0"),
Ok(block) => return (block.0.prefilled_txs.len() + block.0.short_ids.len()).try_into().unwrap(),
Err(err) => {
if err.to_string().starts_with("unsupported segwit version") {
return str_to_c_string("unsupported segwit version")
return -2;
}

return str_to_c_string("1")
return -1;
}
}
}
Expand Down
17 changes: 9 additions & 8 deletions targets/cmpctblocks.cpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
#include <fuzzer/FuzzedDataProvider.h>
#include <string>
#include <iostream>

#include "cmpctblocks.h"
#include "bitcoin/src/blockencodings.h"
#include "bitcoin/src/streams.h"

extern "C" char* rust_bitcoin_cmpctblocks(uint8_t *data, size_t len);
extern "C" int rust_bitcoin_cmpctblocks(uint8_t *data, size_t len);

std::string CmpctBlocksCore(Span<const uint8_t> buffer)
int CmpctBlocksCore(Span<const uint8_t> buffer)
{
DataStream ds{buffer};
CBlockHeaderAndShortTxIDs block_header_and_short_txids;
try {
ds >> block_header_and_short_txids;
} catch (const std::ios_base::failure& e) {
if (std::string(e.what()).find("Superfluous witness record") != std::string::npos)
return "Superfluous witness record";
return "1";
return -2;
return -1;
}
return "0";
return block_header_and_short_txids.BlockTxCount();
}

void CmpctBlocks(FuzzedDataProvider& provider)
{
std::vector<uint8_t> buffer{provider.ConsumeRemainingBytes<uint8_t>()};
std::string core{CmpctBlocksCore(buffer)};
std::string rust_bitcoin{rust_bitcoin_cmpctblocks(buffer.data(), buffer.size())};
int core{CmpctBlocksCore(buffer)};
int rust_bitcoin{rust_bitcoin_cmpctblocks(buffer.data(), buffer.size())};

if (core == "Superfluous witness record" || rust_bitcoin == "unsupported segwit version")
if (core == -2 || rust_bitcoin == -2)
return;

assert(core == rust_bitcoin);
Expand Down

0 comments on commit 603cc2a

Please sign in to comment.