aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG5
-rw-r--r--fuzz/fuzz_targets/does_not_decode_invalid_registers.rs270
-rw-r--r--src/long_mode/mod.rs8
3 files changed, 278 insertions, 5 deletions
diff --git a/CHANGELOG b/CHANGELOG
index f471751..4653f57 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,4 @@
-## 1.3.0
+## 1.2.1
* fix incorrect register numbers used in `RegSpec::r12()` and `RegSpec::r13()`
and smaller-size variants (thank you @tokatoka!)
@@ -22,6 +22,9 @@
`vpmov*2m` with nonsense `k8..k15` selected. to real hardware, this bit
sequence is an invalid instruction, and so it is now invalid to yaxpeax-x86
as well.
+* fix incorrect `RegisterBank` names in `long_mode`. in a previous
+ reorganization register bank numbers were changed and the names were updated to
+ match for `protected_mode` and `real_mode`, but `long_mode` was overlooked.
## 1.2.0
* fix incorrect old yaxpeax-arch version selection for ffi crates
diff --git a/fuzz/fuzz_targets/does_not_decode_invalid_registers.rs b/fuzz/fuzz_targets/does_not_decode_invalid_registers.rs
index 0f32f73..31b1004 100644
--- a/fuzz/fuzz_targets/does_not_decode_invalid_registers.rs
+++ b/fuzz/fuzz_targets/does_not_decode_invalid_registers.rs
@@ -11,20 +11,290 @@ fuzz_target!(|data: &[u8]| {
let x86_16_decoder = yaxpeax_x86::real_mode::InstDecoder::default();
if let Ok(inst) = x86_64_decoder.decode_slice(data) {
+ use yaxpeax_x86::long_mode::Operand;
let mut res = String::new();
inst.write_to(&mut res).expect("format does not panic");
assert!(!res.contains("BUG"));
+ for i in 0..inst.operand_count() {
+ match inst.operand(i) {
+ Operand::Register(reg) => {
+ assert!(!reg.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMerge(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMergeSae(r1, r2, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMergeSaeNoround(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDeref(r1) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegDisp(r1, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegScale(r1, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBase(r1, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseDisp(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegScaleDisp(r1, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScale(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleDisp(r1, r2, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDerefMasked(r1, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDispMasked(r1, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegScaleMasked(r1, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseMasked(r1, r2, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseDispMasked(r1, r2, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegScaleDispMasked(r1, _, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleMasked(r1, r2, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleDispMasked(r1, r2, _, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::Nothing => {
+ panic!("`Nothing` should not be an operand listed in `inst.operand_count()`");
+ }
+ _ => {
+ /* operands with no register - immediates or a non-rip-relative displacement */
+ }
+ }
+ }
};
if let Ok(inst) = x86_32_decoder.decode_slice(data) {
+ use yaxpeax_x86::protected_mode::Operand;
let mut res = String::new();
inst.write_to(&mut res).expect("format does not panic");
assert!(!res.contains("BUG"));
+ for i in 0..inst.operand_count() {
+ match inst.operand(i) {
+ Operand::Register(reg) => {
+ assert!(!reg.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMerge(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMergeSae(r1, r2, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMergeSaeNoround(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDeref(r1) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegDisp(r1, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegScale(r1, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBase(r1, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseDisp(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegScaleDisp(r1, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScale(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleDisp(r1, r2, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDerefMasked(r1, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDispMasked(r1, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegScaleMasked(r1, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseMasked(r1, r2, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseDispMasked(r1, r2, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegScaleDispMasked(r1, _, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleMasked(r1, r2, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleDispMasked(r1, r2, _, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::Nothing => {
+ panic!("`Nothing` should not be an operand listed in `inst.operand_count()`");
+ }
+ _ => {
+ /* operands with no register - immediates or a non-rip-relative displacement */
+ }
+ }
+ }
};
if let Ok(inst) = x86_16_decoder.decode_slice(data) {
+ use yaxpeax_x86::real_mode::Operand;
let mut res = String::new();
inst.write_to(&mut res).expect("format does not panic");
assert!(!res.contains("BUG"));
+ for i in 0..inst.operand_count() {
+ match inst.operand(i) {
+ Operand::Register(reg) => {
+ assert!(!reg.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMerge(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMergeSae(r1, r2, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegisterMaskMergeSaeNoround(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDeref(r1) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegDisp(r1, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegScale(r1, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBase(r1, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseDisp(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegScaleDisp(r1, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScale(r1, r2, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleDisp(r1, r2, _, _) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDerefMasked(r1, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegDispMasked(r1, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegScaleMasked(r1, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseMasked(r1, r2, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseDispMasked(r1, r2, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegScaleDispMasked(r1, _, _, r2) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleMasked(r1, r2, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::RegIndexBaseScaleDispMasked(r1, r2, _, _, r3) => {
+ assert!(!r1.class().name().contains("BUG"));
+ assert!(!r2.class().name().contains("BUG"));
+ assert!(!r3.class().name().contains("BUG"));
+ }
+ Operand::Nothing => {
+ panic!("`Nothing` should not be an operand listed in `inst.operand_count()`");
+ }
+ _ => {
+ /* operands with no register - immediates or a non-rip-relative displacement */
+ }
+ }
+ }
};
});
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs
index 4eb0a36..439417a 100644
--- a/src/long_mode/mod.rs
+++ b/src/long_mode/mod.rs
@@ -789,16 +789,16 @@ pub struct RegisterClass {
}
const REGISTER_CLASS_NAMES: &[&'static str] = &[
- "qword",
- "BUG. PLEASE REPORT.",
- "dword",
"BUG. PLEASE REPORT.",
+ "byte",
"word",
"BUG. PLEASE REPORT.",
- "byte",
+ "dword",
"BUG. PLEASE REPORT.",
"rex-byte",
"BUG. PLEASE REPORT.",
+ "qword",
+ "BUG. PLEASE REPORT.",
"cr",
"BUG. PLEASE REPORT.",
"dr",