summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG9
-rw-r--r--fuzz/.gitignore4
-rw-r--r--fuzz/Cargo.lock250
-rw-r--r--fuzz/Cargo.toml22
-rw-r--r--fuzz/fuzz_targets/display_does_not_panic.rs16
-rw-r--r--src/lib.rs26
-rw-r--r--tests/test.rs17
7 files changed, 333 insertions, 11 deletions
diff --git a/CHANGELOG b/CHANGELOG
index db40a12..8c738cf 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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}");
+ }
+});
diff --git a/src/lib.rs b/src/lib.rs
index da50fc4..4087811 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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);
+}