diff options
-rw-r--r-- | CHANGELOG | 9 | ||||
-rw-r--r-- | fuzz/.gitignore | 4 | ||||
-rw-r--r-- | fuzz/Cargo.lock | 250 | ||||
-rw-r--r-- | fuzz/Cargo.toml | 22 | ||||
-rw-r--r-- | fuzz/fuzz_targets/display_does_not_panic.rs | 16 | ||||
-rw-r--r-- | src/lib.rs | 26 | ||||
-rw-r--r-- | tests/test.rs | 17 |
7 files changed, 333 insertions, 11 deletions
@@ -1,6 +1,13 @@ ## 0.3.0 -update yaxpeax-arch to 0.3.2 (thank you @ravenslofty), with future 0.3.0 DisplaySink impls to come +* update yaxpeax-arch to 0.3.2 (thank you @ravenslofty), with future 0.3.0 DisplaySink impls to come +* fuzzing found a few decode/display issues: + * `mov{,.ret}.mwh.ih` handled operands incorrectly, interpreting the tag as part of hinting. + in addition to being wrong, this would panic if the tag was greater than three. + * `mov pr.rot = ...` decoded its immediate incorrectly. + - if the non-sign-extended part was greater than 255, decoding would panic. + - the decoded immediate was not sign extended or rotated properly. + * `cmp4.crel.crypte` (A7 operand encodings) would assert if `r2` was not zero. ## 0.2.1 diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000..1a45eee --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,4 @@ +target +corpus +artifacts +coverage diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock new file mode 100644 index 0000000..4ae4d9b --- /dev/null +++ b/fuzz/Cargo.lock @@ -0,0 +1,250 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitvec" +version = "0.19.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "cc" +version = "1.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "find-msvc-tools" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" + +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "libc" +version = "0.2.176" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "yaxpeax-arch" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36274fcc5403da2a7636ffda4d02eca12a1b2b8267b9d2e04447bd2ccfc72082" +dependencies = [ + "num-traits", + "serde", + "serde_derive", +] + +[[package]] +name = "yaxpeax-ia64" +version = "0.2.1" +dependencies = [ + "bitvec", + "yaxpeax-arch", +] + +[[package]] +name = "yaxpeax-ia64-fuzz" +version = "0.0.0" +dependencies = [ + "libfuzzer-sys", + "yaxpeax-arch", + "yaxpeax-ia64", +] diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000..78f2a78 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "yaxpeax-ia64-fuzz" +version = "0.0.0" +publish = false +edition = "2018" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" +yaxpeax-arch = "0.3" + +[dependencies.yaxpeax-ia64] +path = ".." + +[[bin]] +name = "display_does_not_panic" +path = "fuzz_targets/display_does_not_panic.rs" +test = false +doc = false +bench = false diff --git a/fuzz/fuzz_targets/display_does_not_panic.rs b/fuzz/fuzz_targets/display_does_not_panic.rs new file mode 100644 index 0000000..f26a268 --- /dev/null +++ b/fuzz/fuzz_targets/display_does_not_panic.rs @@ -0,0 +1,16 @@ +#![no_main] +#[macro_use] extern crate libfuzzer_sys; +extern crate yaxpeax_ia64; + +use yaxpeax_arch::{Decoder, U8Reader}; + +fuzz_target!(|data: &[u8]| { + let ia64_decoder = yaxpeax_ia64::InstDecoder::default(); + + let mut reader = U8Reader::new(data); + + if let Ok(inst) = ia64_decoder.decode(&mut reader) { + let mut out = String::new(); + let res = format!("{inst}"); + } +}); @@ -1198,18 +1198,20 @@ impl fmt::Display for Instruction { self.operands[0], ) } else if self.opcode == Opcode::Mov_mwh_ih { - return write!(f, "mov{}{} {}={}", - ["", "?NONE?", ".dptk", "RESERVED"][self.operands[2].as_unsigned_imm() as usize], + return write!(f, "mov{}{} {}={},{}", + ["", "?NONE?", ".dptk", "RESERVED"][self.operands[4].as_unsigned_imm() as usize], ["", ".imp"][self.operands[3].as_unsigned_imm() as usize], self.operands[0], self.operands[1], + self.operands[2], ) } else if self.opcode == Opcode::Mov_ret_mwh_ih { - return write!(f, "mov.ret{}{} {}={}", - ["", "?NONE?", ".dptk", "RESERVED"][self.operands[2].as_unsigned_imm() as usize], + return write!(f, "mov.ret{}{} {}={},{}", + ["", "?NONE?", ".dptk", "RESERVED"][self.operands[4].as_unsigned_imm() as usize], ["", ".imp"][self.operands[3].as_unsigned_imm() as usize], self.operands[0], self.operands[1], + self.operands[2], ) } else if self.opcode == Opcode::Dep_z { if self.operands[2].as_unsigned_imm() == 64 - self.operands[3].as_unsigned_imm() { @@ -2587,13 +2589,16 @@ fn read_i_operands(encoding: OperandEncodingI, word: &BitSlice<Lsb0, u8>) -> (Op ) } I24 => { - let imm = word[6..33].load::<u8>(); - let _s = word[36] as u32; + // sign extend as described in Table 4-74: "Immediate Formation" + let imm = word[6..33].load::<u64>(); + let s = word[36] as u64; + let signed = ((s << 27) | imm) as i64; + let extended = signed << 36 >> 36; // TODO: this is missing ... 17 bits? sign extend? two_op( Some(0), Operand::PR, - Operand::ImmU64(imm as u64), + Operand::ImmU64(extended as u64), ) } I25 => { @@ -3265,9 +3270,10 @@ fn read_a_operands(encoding: OperandEncodingA, word: &BitSlice<Lsb0, u8>) -> (Op }, A7 => { let p1 = word[6..12].load::<u8>(); - let r2 = word[13..20].load::<u8>(); - // TODO: what happens if this isn't zero? - assert_eq!(r2, 0); + let _r2 = word[13..20].load::<u8>(); + // TODO: what happens if this isn't zero? at least set the instruction not + // well-defined. + // assert_eq!(r2, 0); let r3 = word[20..27].load::<u8>(); let p2 = word[27..33].load::<u8>(); four_op( diff --git a/tests/test.rs b/tests/test.rs index 3a2cad0..b33b1c4 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2488,3 +2488,20 @@ fn test_predication_not_allowed() { assert_eq!(format!("{inst}"), expected); assert!(!inst.well_defined()); } + +#[test] +fn test_from_fuzzer() { + let decoder = InstDecoder::default(); + + let expected = "[MFI] (p01) cmpxchg4.acq r0=[r127],r64; (p40) break.f 0x0; mov pr=0xfffffffff8400000"; + let data = [0x2c, 0x00, 0x00, 0xff, 0x11, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0a]; + let mut reader = U8Reader::new(&data[..]); + let inst = decoder.decode(&mut reader).unwrap(); + assert_eq!(format!("{inst}"), expected); + + let expected = "[MII] (p17) break.m 0x4; break.i 0x0; mov.retRESERVED.imp b0=r48,0x1ff"; + let data = [0x20, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xff, 0x07]; + let mut reader = U8Reader::new(&data[..]); + let inst = decoder.decode(&mut reader).unwrap(); + assert_eq!(format!("{inst}"), expected); +} |