Merge pull request #63 from TheBlueMatt/master
Update fuzz target boilerplate to match rust-lightning
This commit is contained in:
commit
15fd85b9d0
|
@ -5,9 +5,18 @@ rust:
|
|||
- nightly
|
||||
- 1.14.0
|
||||
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install -y binutils-dev libunwind8-dev
|
||||
|
||||
install:
|
||||
- git clone https://github.com/bitcoin/secp256k1.git
|
||||
- cd secp256k1
|
||||
- ./autogen.sh && ./configure && make && sudo make install
|
||||
- sudo ldconfig /usr/local/lib
|
||||
- cd ..
|
||||
|
||||
script:
|
||||
- cargo build --verbose
|
||||
- cargo test --verbose
|
||||
- if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi
|
||||
|
|
|
@ -17,6 +17,7 @@ path = "src/lib.rs"
|
|||
|
||||
[features]
|
||||
bitcoinconsenus = ["bitcoinconsensus"]
|
||||
fuzztarget = ["secp256k1/fuzztarget"]
|
||||
|
||||
[dependencies]
|
||||
bitcoin-bech32 = "0.5.1"
|
||||
|
@ -29,7 +30,5 @@ strason = "0.3"
|
|||
bitcoinconsensus = { version = "0.16", optional=true }
|
||||
|
||||
[dependencies.secp256k1]
|
||||
version = "0.8"
|
||||
features = [ "rand", "serde" ]
|
||||
|
||||
|
||||
version = "0.9"
|
||||
features = [ "rand" ]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
[package]
|
||||
name = "bitcoin-fuzz"
|
||||
version = "0.0.1"
|
||||
|
@ -8,15 +7,31 @@ publish = false
|
|||
[package.metadata]
|
||||
cargo-fuzz = true
|
||||
|
||||
[dependencies.bitcoin]
|
||||
path = ".."
|
||||
[dependencies.libfuzzer-sys]
|
||||
git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
|
||||
[features]
|
||||
afl_fuzz = ["afl"]
|
||||
honggfuzz_fuzz = ["honggfuzz"]
|
||||
|
||||
[dependencies]
|
||||
honggfuzz = { version = "0.5", optional = true }
|
||||
afl = { version = "0.3", optional = true }
|
||||
bitcoin = { path = "..", features = ["fuzztarget"] }
|
||||
|
||||
# Prevent this from interfering with workspaces
|
||||
[workspace]
|
||||
members = ["."]
|
||||
|
||||
[[bin]]
|
||||
name = "fuzzer_script_1"
|
||||
path = "fuzzers/fuzzer_script_1.rs"
|
||||
name = "deserialize_block"
|
||||
path = "fuzz_targets/deserialize_block.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "deserialize_script"
|
||||
path = "fuzz_targets/deserialize_script.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "deserialize_transaction"
|
||||
path = "fuzz_targets/deserialize_transaction.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "deserialize_address"
|
||||
path = "fuzz_targets/deserialize_address.rs"
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
extern crate bitcoin;
|
||||
use std::str::FromStr;
|
||||
fn do_test(data: &[u8]) {
|
||||
let data_str = String::from_utf8_lossy(data);
|
||||
let addr = match bitcoin::util::address::Address::from_str(&data_str) {
|
||||
Ok(addr) => addr,
|
||||
Err(_) => return,
|
||||
};
|
||||
assert_eq!(addr.to_string(), data_str);
|
||||
}
|
||||
|
||||
#[cfg(feature = "afl")]
|
||||
extern crate afl;
|
||||
#[cfg(feature = "afl")]
|
||||
fn main() {
|
||||
afl::read_stdio_bytes(|data| {
|
||||
do_test(&data);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
#[macro_use] extern crate honggfuzz;
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
fn main() {
|
||||
loop {
|
||||
fuzz!(|data| {
|
||||
do_test(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
|
||||
let mut b = 0;
|
||||
for (idx, c) in hex.as_bytes().iter().enumerate() {
|
||||
b <<= 4;
|
||||
match *c {
|
||||
b'A'...b'F' => b |= c - b'A' + 10,
|
||||
b'a'...b'f' => b |= c - b'a' + 10,
|
||||
b'0'...b'9' => b |= c - b'0',
|
||||
_ => panic!("Bad hex"),
|
||||
}
|
||||
if (idx & 1) == 1 {
|
||||
out.push(b);
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_crash() {
|
||||
let mut a = Vec::new();
|
||||
extend_vec_from_hex("00000000", &mut a);
|
||||
super::do_test(&a);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
extern crate bitcoin;
|
||||
type BResult = Result<bitcoin::blockdata::block::Block, bitcoin::util::Error>;
|
||||
fn do_test(data: &[u8]) {
|
||||
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
||||
}
|
||||
|
||||
#[cfg(feature = "afl")]
|
||||
extern crate afl;
|
||||
#[cfg(feature = "afl")]
|
||||
fn main() {
|
||||
afl::read_stdio_bytes(|data| {
|
||||
do_test(&data);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
#[macro_use] extern crate honggfuzz;
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
fn main() {
|
||||
loop {
|
||||
fuzz!(|data| {
|
||||
do_test(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
|
||||
let mut b = 0;
|
||||
for (idx, c) in hex.as_bytes().iter().enumerate() {
|
||||
b <<= 4;
|
||||
match *c {
|
||||
b'A'...b'F' => b |= c - b'A' + 10,
|
||||
b'a'...b'f' => b |= c - b'a' + 10,
|
||||
b'0'...b'9' => b |= c - b'0',
|
||||
_ => panic!("Bad hex"),
|
||||
}
|
||||
if (idx & 1) == 1 {
|
||||
out.push(b);
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_crash() {
|
||||
let mut a = Vec::new();
|
||||
extend_vec_from_hex("00", &mut a);
|
||||
super::do_test(&a);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
extern crate bitcoin;
|
||||
type BResult = Result<bitcoin::blockdata::script::Script, bitcoin::util::Error>;
|
||||
fn do_test(data: &[u8]) {
|
||||
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
||||
}
|
||||
|
||||
#[cfg(feature = "afl")]
|
||||
extern crate afl;
|
||||
#[cfg(feature = "afl")]
|
||||
fn main() {
|
||||
afl::read_stdio_bytes(|data| {
|
||||
do_test(&data);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
#[macro_use] extern crate honggfuzz;
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
fn main() {
|
||||
loop {
|
||||
fuzz!(|data| {
|
||||
do_test(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
|
||||
let mut b = 0;
|
||||
for (idx, c) in hex.as_bytes().iter().enumerate() {
|
||||
b <<= 4;
|
||||
match *c {
|
||||
b'A'...b'F' => b |= c - b'A' + 10,
|
||||
b'a'...b'f' => b |= c - b'a' + 10,
|
||||
b'0'...b'9' => b |= c - b'0',
|
||||
_ => panic!("Bad hex"),
|
||||
}
|
||||
if (idx & 1) == 1 {
|
||||
out.push(b);
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_crash() {
|
||||
let mut a = Vec::new();
|
||||
extend_vec_from_hex("00", &mut a);
|
||||
super::do_test(&a);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
extern crate bitcoin;
|
||||
type BResult = Result<bitcoin::blockdata::transaction::Transaction, bitcoin::util::Error>;
|
||||
fn do_test(data: &[u8]) {
|
||||
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
||||
}
|
||||
|
||||
#[cfg(feature = "afl")]
|
||||
extern crate afl;
|
||||
#[cfg(feature = "afl")]
|
||||
fn main() {
|
||||
afl::read_stdio_bytes(|data| {
|
||||
do_test(&data);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
#[macro_use] extern crate honggfuzz;
|
||||
#[cfg(feature = "honggfuzz")]
|
||||
fn main() {
|
||||
loop {
|
||||
fuzz!(|data| {
|
||||
do_test(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
|
||||
let mut b = 0;
|
||||
for (idx, c) in hex.as_bytes().iter().enumerate() {
|
||||
b <<= 4;
|
||||
match *c {
|
||||
b'A'...b'F' => b |= c - b'A' + 10,
|
||||
b'a'...b'f' => b |= c - b'a' + 10,
|
||||
b'0'...b'9' => b |= c - b'0',
|
||||
_ => panic!("Bad hex"),
|
||||
}
|
||||
if (idx & 1) == 1 {
|
||||
out.push(b);
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_crash() {
|
||||
let mut a = Vec::new();
|
||||
extend_vec_from_hex("00", &mut a);
|
||||
super::do_test(&a);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#![no_main]
|
||||
#[macro_use] extern crate libfuzzer_sys;
|
||||
extern crate bitcoin;
|
||||
|
||||
type BResult = Result<bitcoin::blockdata::script::Script, bitcoin::util::Error>;
|
||||
//type BResult = Result<bitcoin::blockdata::transaction::Transaction, bitcoin::util::Error>;
|
||||
//type BResult = Result<bitcoin::blockdata::transaction::TxIn, bitcoin::util::Error>;
|
||||
//type BResult = Result<bitcoin::blockdata::transaction::TxOut, bitcoin::util::Error>;
|
||||
//type BResult = Result<bitcoin::network::constants::Network, bitcoin::util::Error>;
|
||||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
||||
});
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
<EFBFBD><EFBFBD><EFBFBD>EEE
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>2q<>
|
|
@ -0,0 +1 @@
|
|||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
<EFBFBD>
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>
|
|
@ -0,0 +1 @@
|
|||
ΙΑ
|
|
@ -0,0 +1 @@
|
|||
ェホユチ
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
Ś¬ŹCCCACCCŢŚ¬ŞCCCA‹ŹCCCACPC,¬3·¬ŹCCCC€
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
<EFBFBD>ウウウウウウウウウウウウヤウウウウウウウウウウウヤウウウウウウウウウウウウウウウウヤウウウオ
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
cargo install honggfuzz
|
||||
set +e
|
||||
for TARGET in fuzz_targets/*; do
|
||||
FILENAME=$(basename $TARGET)
|
||||
FILE="${FILENAME%.*}"
|
||||
HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz" HFUZZ_RUN_ARGS="-N1000000 --exit_upon_crash -v" cargo hfuzz run $FILE
|
||||
if [ -f hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT ]; then
|
||||
cat hfuzz_workspace/$FILE/HONGGFUZZ.REPORT.TXT
|
||||
for CASE in hfuzz_workspace/$FILE/SIG*; do
|
||||
cat $CASE | xxd -p
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
done
|
|
@ -28,7 +28,6 @@ use std::default::Default;
|
|||
use std::{error, fmt};
|
||||
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2::Sha256;
|
||||
use serde;
|
||||
|
||||
use blockdata::opcodes;
|
||||
|
@ -39,6 +38,9 @@ use util::hash::Hash160;
|
|||
#[cfg(feature="bitcoinconsensus")] use std::convert;
|
||||
#[cfg(feature="bitcoinconsensus")] use util::hash::Sha256dHash;
|
||||
|
||||
#[cfg(feature="fuzztarget")] use util::sha2::Sha256;
|
||||
#[cfg(not(feature="fuzztarget"))] use crypto::sha2::Sha256;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
/// A Bitcoin script
|
||||
pub struct Script(Box<[u8]>);
|
||||
|
|
|
@ -241,8 +241,9 @@ impl FromStr for Address {
|
|||
|
||||
fn from_str(s: &str) -> Result<Address, Error> {
|
||||
// bech32 (note that upper or lowercase is allowed but NOT mixed case)
|
||||
if &s.as_bytes()[0..3] == b"bc1" || &s.as_bytes()[0..3] == b"tb1" ||
|
||||
&s.as_bytes()[0..3] == b"BC1" || &s.as_bytes()[0..3] == b"TB1" {
|
||||
if s.len() >= 3 &&
|
||||
(&s.as_bytes()[0..3] == b"bc1" || &s.as_bytes()[0..3] == b"tb1" ||
|
||||
&s.as_bytes()[0..3] == b"BC1" || &s.as_bytes()[0..3] == b"TB1") {
|
||||
let witprog = try!(WitnessProgram::from_address(s));
|
||||
let network = match witprog.network() {
|
||||
bitcoin_bech32::constants::Network::Bitcoin => Network::Bitcoin,
|
||||
|
|
|
@ -28,14 +28,15 @@ use crypto::digest::Digest;
|
|||
use crypto::hmac::Hmac;
|
||||
use crypto::mac::Mac;
|
||||
use crypto::ripemd160::Ripemd160;
|
||||
use crypto::sha2::Sha256;
|
||||
use crypto::sha2::Sha512;
|
||||
use secp256k1::key::{PublicKey, SecretKey};
|
||||
use secp256k1::{self, Secp256k1};
|
||||
|
||||
use network::constants::Network;
|
||||
use util::base58;
|
||||
|
||||
#[cfg(feature="fuzztarget")] use util::sha2::{Sha256, Sha512};
|
||||
#[cfg(not(feature="fuzztarget"))] use crypto::sha2::{Sha256, Sha512};
|
||||
|
||||
/// A chain code
|
||||
pub struct ChainCode([u8; 32]);
|
||||
impl_array_newtype!(ChainCode, u8, 32);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
use secp256k1::{self, Secp256k1};
|
||||
use secp256k1::key::{PublicKey, SecretKey};
|
||||
use blockdata::{opcodes, script};
|
||||
use crypto::{hmac, sha2};
|
||||
use crypto::hmac;
|
||||
use crypto::mac::Mac;
|
||||
|
||||
use std::{error, fmt};
|
||||
|
@ -28,6 +28,9 @@ use std::{error, fmt};
|
|||
use network::constants::Network;
|
||||
use util::{address, hash};
|
||||
|
||||
#[cfg(feature="fuzztarget")] use util::sha2;
|
||||
#[cfg(not(feature="fuzztarget"))] use crypto::sha2;
|
||||
|
||||
/// Encoding of "pubkey here" in script; from bitcoin core `src/script/script.h`
|
||||
static PUBKEY: u8 = 0xFE;
|
||||
|
||||
|
|
|
@ -26,13 +26,15 @@ use serde;
|
|||
|
||||
use byteorder::{LittleEndian, WriteBytesExt};
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2::Sha256;
|
||||
use crypto::ripemd160::Ripemd160;
|
||||
|
||||
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
|
||||
use network::serialize::{SimpleEncoder, RawEncoder, BitcoinHash};
|
||||
use util::uint::Uint256;
|
||||
|
||||
#[cfg(feature="fuzztarget")] use util::sha2::Sha256;
|
||||
#[cfg(not(feature="fuzztarget"))] use crypto::sha2::Sha256;
|
||||
|
||||
/// Hex deserialization error
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum HexError {
|
||||
|
|
|
@ -28,6 +28,9 @@ pub mod iter;
|
|||
pub mod misc;
|
||||
pub mod uint;
|
||||
|
||||
#[cfg(feature = "fuzztarget")]
|
||||
pub mod sha2;
|
||||
|
||||
use std::{error, fmt, io};
|
||||
|
||||
use bitcoin_bech32;
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
//! fuzztarget-only Sha2 context with a dummy Sha256 and Sha512 hashers.
|
||||
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
/// Dummy Sha256 that hashes the input, but only returns the first byte of output, masking the
|
||||
/// rest to 0s.
|
||||
pub struct Sha256 {
|
||||
state: sha2::Sha256,
|
||||
}
|
||||
|
||||
impl Sha256 {
|
||||
/// Constructs a new dummy Sha256 context
|
||||
pub fn new() -> Sha256 {
|
||||
Sha256 {
|
||||
state: sha2::Sha256::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for Sha256 {
|
||||
fn result(&mut self, data: &mut [u8]) {
|
||||
self.state.result(data);
|
||||
for i in 1..32 {
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn input(&mut self, data: &[u8]) { self.state.input(data); }
|
||||
fn reset(&mut self) { self.state.reset(); }
|
||||
fn output_bits(&self) -> usize { self.state.output_bits() }
|
||||
fn block_size(&self) -> usize { self.state.block_size() }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
/// Dummy Sha512 that hashes the input, but only returns the first byte of output, masking the
|
||||
/// rest to 0s.
|
||||
pub struct Sha512 {
|
||||
state: sha2::Sha512,
|
||||
}
|
||||
|
||||
impl Sha512 {
|
||||
/// Constructs a new dummy Sha512 context
|
||||
pub fn new() -> Sha512 {
|
||||
Sha512 {
|
||||
state: sha2::Sha512::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Digest for Sha512 {
|
||||
fn result(&mut self, data: &mut [u8]) {
|
||||
self.state.result(data);
|
||||
for i in 1..64 {
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn input(&mut self, data: &[u8]) { self.state.input(data); }
|
||||
fn reset(&mut self) { self.state.reset(); }
|
||||
fn output_bits(&self) -> usize { self.state.output_bits() }
|
||||
fn block_size(&self) -> usize { self.state.block_size() }
|
||||
}
|
Loading…
Reference in New Issue