From 83b12fc09a69cc5324f6f002b8c52382d4b236d1 Mon Sep 17 00:00:00 2001
From: iximeow <me@iximeow.net>
Date: Sat, 16 Dec 2023 15:54:13 -0800
Subject: fix incorrect register class names in long_mode

also adjust changelog for a 1.2.1 version again, no new interfaces to go
with these bugfixes.
---
 .../does_not_decode_invalid_registers.rs           | 270 +++++++++++++++++++++
 1 file changed, 270 insertions(+)

(limited to 'fuzz')

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 */
+                }
+            }
+        }
     };
 });
-- 
cgit v1.1