From dd8bd5ce0772b08c271205508e48e98ef1c58ea8 Mon Sep 17 00:00:00 2001 From: iximeow Date: Mon, 24 Jun 2024 14:06:22 -0700 Subject: justify the current max instruction length this is also checked by a new fuzz target --- src/lib.rs | 36 ++++++++++++++++++++++++++++++++++++ src/long_mode/display.rs | 4 +--- src/protected_mode/display.rs | 4 +--- src/real_mode/display.rs | 4 +--- 4 files changed, 39 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 7ab6cb8..93274f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -138,6 +138,42 @@ pub use protected_mode::Arch as x86_32; pub mod real_mode; pub use real_mode::Arch as x86_16; +// this exists to size `InstructionTextBuffer`'s buffer. it ideally would come from an `Arch` +// impl, or something related to `Arch`, but i'm not yet sure how to wire that up into +// yaxpeax-arch. so instead calculate an appropriate max size for all of 16-bit/32-bit/64-bit +// instruction printing that `InstructionTextBuffer` can be used for. +// +// `InstructionTextBuffer` prints an `InstructionDisplayer`, which means either intel syntax or +// pseudo-C. in the future, at&t probably, as well. +// +// the pseudo-C syntax's max length would be something like: +// ``` +// xacquire xrelease lock { repnz qword if /* signed */ greater_or_equal(rflags) then jmp gs:[xmm31 + +// xmm31 * 8 + 0x12345678]{k7}{z}{rne-sae} } +// ``` +// (which is nonsensical) or for an unknown opcode, +// ``` +// xacquire xrelease lock { op0 = op(op0, op1, op2, op3) } +// ``` +// where `opN` is an operand. the longest operand, same as above, would be something like +// ``` +// gs:[xmm31 + xmm31 * 8 + 0x12345678]{k7}{z}{rne-sae} +// ``` +// for a length like 262 bytes of operand, 55 bytes of prefixes and syntax, and another up-to-20 +// bytes of opcode. +// +// the longest contextualize_c might write is around 337 bytes. round up to 512 because it's.. not +// much extra. +// +// the same reasoning for intel syntax yields a smaller instruction: +// ``` +// xacquire xrelease lock op op1, op2, op3, op4 +// ``` +// where the longest operands are the same as above. this comes out to closer to 307 bytes. 512 +// bytes is still the longest of the two options. +#[allow(dead_code)] // can be an unused constant in some library configurations +const MAX_INSTRUCTION_LEN: usize = 512; + const MEM_SIZE_STRINGS: [&'static str; 65] = [ "BUG", "byte", "word", "BUG", "dword", "ptr", "far", "BUG", "qword", diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 1193f35..89d952b 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -4410,9 +4410,7 @@ mod buffer_sink { /// settings format instructions identically to their corresponding `fmt::Display`. pub fn new() -> Self { let mut buf = alloc::string::String::new(); - // TODO: move 512 out to a MAX_INSTRUCTION_LEN const and appropriate justification (and - // fuzzing and ..) - buf.reserve(512); + buf.reserve(crate::MAX_INSTRUCTION_LEN); Self { content: buf, } diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index db12878..321b5b5 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -2955,9 +2955,7 @@ mod buffer_sink { /// settings format instructions identically to their corresponding `fmt::Display`. pub fn new() -> Self { let mut buf = alloc::string::String::new(); - // TODO: move 512 out to a MAX_INSTRUCTION_LEN const and appropriate justification (and - // fuzzing and ..) - buf.reserve(512); + buf.reserve(crate::MAX_INSTRUCTION_LEN); Self { content: buf, } diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs index e8bd191..669b8d7 100644 --- a/src/real_mode/display.rs +++ b/src/real_mode/display.rs @@ -2957,9 +2957,7 @@ mod buffer_sink { /// settings format instructions identically to their corresponding `fmt::Display`. pub fn new() -> Self { let mut buf = alloc::string::String::new(); - // TODO: move 512 out to a MAX_INSTRUCTION_LEN const and appropriate justification (and - // fuzzing and ..) - buf.reserve(512); + buf.reserve(crate::MAX_INSTRUCTION_LEN); Self { content: buf, } -- cgit v1.1