From: Matt Corallo <649246+TheBlueMatt@users.noreply.github.com> Date: Sun, 13 May 2018 17:13:01 +0000 (-0400) Subject: Merge pull request #24 from yuntai/master X-Git-Tag: v0.0.12~407 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=eccd527a55307b94a5c5c5df7e3ef056440e79b8;hp=4a9d3a5c0ad0ecef1b97329fc08873e18d2ba7fd;p=rust-lightning Merge pull request #24 from yuntai/master fill decode/encode routines for many messages with fuzz targets --- diff --git a/Cargo.toml b/Cargo.toml index e8570e25..3b692790 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ fuzztarget = ["secp256k1/fuzztarget", "bitcoin/fuzztarget"] bitcoin = "0.13" rust-crypto = "0.2" rand = "0.4" -secp256k1 = "0.9" +secp256k1 = { git = "https://github.com/rust-bitcoin/rust-secp256k1", branch = "master" } [build-dependencies] gcc = "0.3" diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 00000000..8bf27ec5 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,3 @@ +hfuzz_target +target +hfuzz_workspace diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 9b718bad..521e93d3 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -18,7 +18,7 @@ honggfuzz_fuzz = ["honggfuzz"] [dependencies] lightning = { path = "..", features = ["fuzztarget"] } bitcoin = { version = "0.13", features = ["fuzztarget"] } -secp256k1 = { version = "0.9", features = ["fuzztarget"] } +secp256k1 = { git = "https://github.com/rust-bitcoin/rust-secp256k1", branch = "master" , features=["fuzztarget"]} rust-crypto = "0.2" honggfuzz = { version = "0.5", optional = true } afl = { version = "0.3", optional = true } @@ -41,3 +41,60 @@ path = "fuzz_targets/channel_target.rs" [[bin]] name = "full_stack_target" path = "fuzz_targets/full_stack_target.rs" + +# message fuzz targets +[[bin]] +name = "msg_accept_channel_target" +path = "fuzz_targets/msg_targets/msg_accept_channel_target.rs" + +[[bin]] +name = "msg_closing_signed_target" +path = "fuzz_targets/msg_targets/msg_closing_signed_target.rs" + +[[bin]] +name = "msg_commitment_signed_target" +path = "fuzz_targets/msg_targets/msg_commitment_signed_target.rs" + +[[bin]] +name = "msg_funding_created_target" +path = "fuzz_targets/msg_targets/msg_funding_created_target.rs" + +[[bin]] +name = "msg_funding_locked_target" +path = "fuzz_targets/msg_targets/msg_funding_locked_target.rs" + +[[bin]] +name = "msg_funding_signed_target" +path = "fuzz_targets/msg_targets/msg_funding_signed_target.rs" + +[[bin]] +name = "msg_open_channel_target" +path = "fuzz_targets/msg_targets/msg_open_channel_target.rs" + +[[bin]] +name = "msg_revoke_and_ack_target" +path = "fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs" + +[[bin]] +name = "msg_shutdown_target" +path = "fuzz_targets/msg_targets/msg_shutdown_target.rs" + +[[bin]] +name = "msg_update_add_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_add_htlc_target.rs" + +[[bin]] +name = "msg_update_fail_malformed_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs" + +[[bin]] +name = "msg_update_fee_target" +path = "fuzz_targets/msg_targets/msg_update_fee_target.rs" + +[[bin]] +name = "msg_update_fulfill_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs" + +[[bin]] +name = "msg_update_fail_htlc_target" +path = "fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs" diff --git a/fuzz/fuzz_targets/msg_targets/gen_target.sh b/fuzz/fuzz_targets/msg_targets/gen_target.sh new file mode 100644 index 00000000..6a107173 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/gen_target.sh @@ -0,0 +1,5 @@ +for target in CommitmentSigned FundingCreated FundingLocked FundingSigned OpenChannel RevokeAndACK Shutdown UpdateAddHTLC UpdateFailHTLC UpdateFailMalformedHTLC UpdateFee UpdateFulfillHTLC AcceptChannel ClosingSigned; do + tn=$(echo $target | sed 's/\([a-z0-9]\)\([A-Z]\)/\1_\L\2/g') + fn=msg_$(echo $tn | tr '[:upper:]' '[:lower:]')_target.rs + cat msg_target_template.txt | sed s/MSG_TARGET/$target/ > $fn +done diff --git a/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs b/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs new file mode 100644 index 00000000..dd44e16a --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_accept_channel_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::AcceptChannel, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs new file mode 100644 index 00000000..4e990e92 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_closing_signed_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::ClosingSigned, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs new file mode 100644 index 00000000..7e0ff45d --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_commitment_signed_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::CommitmentSigned, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs new file mode 100644 index 00000000..ae66f5d3 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_funding_created_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::FundingCreated, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs new file mode 100644 index 00000000..d3570b7e --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_funding_locked_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::FundingLocked, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs b/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs new file mode 100644 index 00000000..3c479382 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_funding_signed_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::FundingSigned, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs b/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs new file mode 100644 index 00000000..f33988b1 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_open_channel_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::OpenChannel, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs b/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs new file mode 100644 index 00000000..495a9ca4 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_revoke_and_ack_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::RevokeAndACK, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs b/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs new file mode 100644 index 00000000..7eabf809 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_shutdown_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::Shutdown, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_target_template.txt b/fuzz/fuzz_targets/msg_targets/msg_target_template.txt new file mode 100644 index 00000000..d5754ad2 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_target_template.txt @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::MSG_TARGET, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs new file mode 100644 index 00000000..674e5bfd --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_update_add_htlc_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::UpdateAddHTLC, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs new file mode 100644 index 00000000..0c4a9f10 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_update_fail_htlc_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::UpdateFailHTLC, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs new file mode 100644 index 00000000..bf64a1ee --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_update_fail_malformed_htlc_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::UpdateFailMalformedHTLC, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs new file mode 100644 index 00000000..817a44d5 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_update_fee_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::UpdateFee, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs b/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs new file mode 100644 index 00000000..e3747e47 --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/msg_update_fulfill_htlc_target.rs @@ -0,0 +1,49 @@ +extern crate lightning; + +use lightning::ln::msgs; +use lightning::util::reset_rng_state; + +use lightning::ln::msgs::{MsgEncodable, MsgDecodable}; + +mod utils; +use utils::slice_to_be16; + +#[inline] +pub fn do_test(data: &[u8]) { + reset_rng_state(); + let mut read_pos = 0; + loop { + test_msg!(msgs::UpdateFulfillHTLC, data, read_pos); + } +} + +#[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 { + use utils::extend_vec_from_hex; + #[test] + fn duplicate_crash() { + let mut a = Vec::new(); + extend_vec_from_hex("00", &mut a); + super::do_test(&a); + } +} diff --git a/fuzz/fuzz_targets/msg_targets/utils.rs b/fuzz/fuzz_targets/msg_targets/utils.rs new file mode 100644 index 00000000..cb4de5eb --- /dev/null +++ b/fuzz/fuzz_targets/msg_targets/utils.rs @@ -0,0 +1,69 @@ +#![macro_use] + +#[allow(dead_code)] +#[inline] +pub fn slice_to_be16(v: &[u8]) -> u16 { + ((v[0] as u16) << 8*1) | + ((v[1] as u16) << 8*0) +} + +#[macro_export] +macro_rules! test_msg { + ($MsgType: path, $data: ident, $read_pos: ident) => { + { + let len = slice_to_be16(get_slice!($data, $read_pos, 2)); + let raw = get_slice!($data, $read_pos, len); + let cb = decode_msg!($MsgType, raw).encode(); + assert_eq!(&raw[..cb.len()], &cb[..]); + } + } +} + +#[macro_export] +macro_rules! decode_msg { + ($MsgType: path, $data: expr) => { + match <($MsgType)>::decode($data) { + Ok(msg) => msg, + Err(e) => match e { + msgs::DecodeError::UnknownRealmByte => return, + msgs::DecodeError::BadPublicKey => return, + msgs::DecodeError::BadSignature => return, + msgs::DecodeError::ExtraAddressesPerType => return, + msgs::DecodeError::WrongLength => return, + } + } + } +} + +#[macro_export] +macro_rules! get_slice { + ($data: ident, $read_pos: ident, $len: expr) => { + { + let slice_len = $len as usize; + if $data.len() < $read_pos + slice_len { + return; + } + $read_pos += slice_len; + &$data[$read_pos - slice_len..$read_pos] + } + } +} + +#[allow(dead_code)] +#[cfg(test)] +pub fn extend_vec_from_hex(hex: &str, out: &mut Vec) { + 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; + } + } +} diff --git a/fuzz/travis-fuzz.sh b/fuzz/travis-fuzz.sh index 5129799a..a60d1185 100755 --- a/fuzz/travis-fuzz.sh +++ b/fuzz/travis-fuzz.sh @@ -1,8 +1,8 @@ #!/bin/bash set -e cargo install --force honggfuzz -for TARGET in fuzz_targets/*; do - FILENAME=$(basename $TARGET) +for TARGET in fuzz_targets/*.rs fuzz_targets/msg_targets/*_target.rs; 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 diff --git a/src/ln/msgs.rs b/src/ln/msgs.rs index 681817a9..ed0b3479 100644 --- a/src/ln/msgs.rs +++ b/src/ln/msgs.rs @@ -613,7 +613,33 @@ impl MsgDecodable for OpenChannel { } impl MsgEncodable for OpenChannel { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = match &self.shutdown_scriptpubkey { + &Some(ref script) => Vec::with_capacity(319 + 2 + script.len()), + &None => Vec::with_capacity(319), + }; + res.extend_from_slice(&serialize(&self.chain_hash).unwrap()); + res.extend_from_slice(&serialize(&self.temporary_channel_id).unwrap()); + res.extend_from_slice(&byte_utils::be64_to_array(self.funding_satoshis)); + res.extend_from_slice(&byte_utils::be64_to_array(self.push_msat)); + res.extend_from_slice(&byte_utils::be64_to_array(self.dust_limit_satoshis)); + res.extend_from_slice(&byte_utils::be64_to_array(self.max_htlc_value_in_flight_msat)); + res.extend_from_slice(&byte_utils::be64_to_array(self.channel_reserve_satoshis)); + res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_minimum_msat)); + res.extend_from_slice(&byte_utils::be32_to_array(self.feerate_per_kw)); + res.extend_from_slice(&byte_utils::be16_to_array(self.to_self_delay)); + res.extend_from_slice(&byte_utils::be16_to_array(self.max_accepted_htlcs)); + res.extend_from_slice(&self.funding_pubkey.serialize()); + res.extend_from_slice(&self.revocation_basepoint.serialize()); + res.extend_from_slice(&self.payment_basepoint.serialize()); + res.extend_from_slice(&self.delayed_payment_basepoint.serialize()); + res.extend_from_slice(&self.htlc_basepoint.serialize()); + res.extend_from_slice(&self.first_per_commitment_point.serialize()); + res.push(self.channel_flags); + if let &Some(ref script) = &self.shutdown_scriptpubkey { + res.extend_from_slice(&byte_utils::be16_to_array(script.len() as u16)); + res.extend_from_slice(&script[..]); + } + res } } @@ -722,7 +748,10 @@ impl MsgDecodable for FundingSigned { } impl MsgEncodable for FundingSigned { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(32+64); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + res.extend_from_slice(&self.signature.serialize_compact(&Secp256k1::without_caps())); + res } } @@ -809,13 +838,20 @@ impl MsgDecodable for UpdateAddHTLC { amount_msat: byte_utils::slice_to_be64(&v[40..48]), payment_hash, cltv_expiry: byte_utils::slice_to_be32(&v[80..84]), - onion_routing_packet: OnionPacket::decode(&v[84..])?, + onion_routing_packet: OnionPacket::decode(&v[84..84+1366])?, }) } } impl MsgEncodable for UpdateAddHTLC { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(32+8+8+32+4+1+1366); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_id)); + res.extend_from_slice(&byte_utils::be64_to_array(self.amount_msat)); + res.extend_from_slice(&self.payment_hash); + res.extend_from_slice(&byte_utils::be32_to_array(self.cltv_expiry)); + res.extend_from_slice(&self.onion_routing_packet.encode()[..]); + res } } @@ -835,7 +871,11 @@ impl MsgDecodable for UpdateFulfillHTLC { } impl MsgEncodable for UpdateFulfillHTLC { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(32+8+32); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_id)); + res.extend_from_slice(&self.payment_preimage); + res } } @@ -853,7 +893,12 @@ impl MsgDecodable for UpdateFailHTLC { } impl MsgEncodable for UpdateFailHTLC { fn encode(&self) -> Vec { - unimplemented!(); + let reason = self.reason.encode(); + let mut res = Vec::with_capacity(32+8+reason.len()); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_id)); + res.extend_from_slice(&reason[..]); + res } } @@ -874,7 +919,12 @@ impl MsgDecodable for UpdateFailMalformedHTLC { } impl MsgEncodable for UpdateFailMalformedHTLC { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(32+8+32+2); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + res.extend_from_slice(&byte_utils::be64_to_array(self.htlc_id)); + res.extend_from_slice(&self.sha256_of_onion); + res.extend_from_slice(&byte_utils::be16_to_array(self.failure_code)); + res } } @@ -901,7 +951,15 @@ impl MsgDecodable for CommitmentSigned { } impl MsgEncodable for CommitmentSigned { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(32+64+2+self.htlc_signatures.len()*64); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + let secp_ctx = Secp256k1::without_caps(); + res.extend_from_slice(&self.signature.serialize_compact(&secp_ctx)); + res.extend_from_slice(&byte_utils::be16_to_array(self.htlc_signatures.len() as u16)); + for i in 0..self.htlc_signatures.len() { + res.extend_from_slice(&self.htlc_signatures[i].serialize_compact(&secp_ctx)); + } + res } } @@ -922,7 +980,11 @@ impl MsgDecodable for RevokeAndACK { } impl MsgEncodable for RevokeAndACK { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(32+32+33); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + res.extend_from_slice(&self.per_commitment_secret); + res.extend_from_slice(&self.next_per_commitment_point.serialize()); + res } } @@ -939,7 +1001,10 @@ impl MsgDecodable for UpdateFee { } impl MsgEncodable for UpdateFee { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(32+4); + res.extend_from_slice(&serialize(&self.channel_id).unwrap()); + res.extend_from_slice(&byte_utils::be32_to_array(self.feerate_per_kw)); + res } } @@ -1141,7 +1206,12 @@ impl MsgDecodable for NodeAnnouncement { } impl MsgEncodable for NodeAnnouncement { fn encode(&self) -> Vec { - unimplemented!(); + let contents = self.contents.encode(); + let mut res = Vec::with_capacity(64 + contents.len()); + let secp_ctx = Secp256k1::without_caps(); + res.extend_from_slice(&self.signature.serialize_compact(&secp_ctx)); + res.extend_from_slice(&contents); + res } } @@ -1196,7 +1266,15 @@ impl MsgDecodable for ChannelAnnouncement { } impl MsgEncodable for ChannelAnnouncement { fn encode(&self) -> Vec { - unimplemented!(); + let secp_ctx = Secp256k1::without_caps(); + let contents = self.contents.encode(); + let mut res = Vec::with_capacity(64 + contents.len()); + res.extend_from_slice(&self.node_signature_1.serialize_compact(&secp_ctx)); + res.extend_from_slice(&self.node_signature_2.serialize_compact(&secp_ctx)); + res.extend_from_slice(&self.bitcoin_signature_1.serialize_compact(&secp_ctx)); + res.extend_from_slice(&self.bitcoin_signature_2.serialize_compact(&secp_ctx)); + res.extend_from_slice(&contents); + res } } @@ -1384,7 +1462,9 @@ impl MsgDecodable for OnionErrorPacket { } impl MsgEncodable for OnionErrorPacket { fn encode(&self) -> Vec { - unimplemented!(); + let mut res = Vec::with_capacity(2 + self.data.len()); + res.extend_from_slice(&byte_utils::be16_to_array(self.data.len() as u16)); + res.extend_from_slice(&self.data); + res } } -