use crate::*;
const DATA_ADDR: u64 = 0x7000;
#[test]
fn test_stack_alignment_16_byte() {
let code = [
0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "RSP is 16-byte aligned");
}
#[test]
fn test_stack_misalignment_8_byte() {
let code = [
0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1008-(0x1008 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1008; emu.run(None).unwrap();
assert_ne!(emu.regs().rsp & 0x0F, 0, "RSP is not 16-byte aligned");
assert_eq!(emu.regs().rsp & 0x07, 0, "RSP is 8-byte aligned");
}
#[test]
fn test_single_push_breaks_alignment() {
let code = [
0x50, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "RSP offset by 8 from 16-byte boundary");
}
#[test]
fn test_two_pushes_restore_alignment() {
let code = [
0x50, 0x53, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "RSP is 16-byte aligned after two pushes");
}
#[test]
fn test_odd_pushes_misalign() {
let code = [
0x50, 0x53, 0x51, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "Three pushes misalign stack");
}
#[test]
fn test_four_pushes_aligned() {
let code = [
0x50, 0x53, 0x51, 0x52, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Four pushes maintain alignment");
}
#[test]
fn test_enter_maintains_alignment() {
let code = [
0xc8, 0x00, 0x00, 0x00, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "ENTER pushes RBP (8 bytes), misaligning");
}
#[test]
fn test_enter_with_even_allocation() {
let code = [
0xc8, 0x10, 0x00, 0x00, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "ENTER 16,0 results in misalignment");
}
#[test]
fn test_enter_with_alignment_padding() {
let code = [
0xc8, 0x08, 0x00, 0x00, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "ENTER 8,0 maintains alignment");
}
#[test]
fn test_enter_leave_alignment_roundtrip() {
let code = [
0xc8, 0x08, 0x00, 0x00, 0xc9, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "ENTER/LEAVE roundtrip preserves alignment");
}
#[test]
fn test_push_imm_alignment() {
let code = [
0x6a, 0x42, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "PUSH immediate breaks alignment");
}
#[test]
fn test_multiple_push_imm_pattern() {
let code = [
0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, 0x6a, 0x04,
0x6a, 0x05, 0x6a, 0x06, 0x6a, 0x07, 0x6a, 0x08,
0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Eight pushes maintain alignment");
}
#[test]
fn test_sub_rsp_16_aligned() {
let code = [
0x48, 0x83, 0xec, 0x10, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "SUB RSP, 16 maintains alignment");
}
#[test]
fn test_sub_rsp_8_misaligned() {
let code = [
0x48, 0x83, 0xec, 0x08, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "SUB RSP, 8 breaks alignment");
}
#[test]
fn test_sub_rsp_32_aligned() {
let code = [
0x48, 0x83, 0xec, 0x20, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "SUB RSP, 32 maintains alignment");
}
#[test]
fn test_sub_rsp_48_aligned() {
let code = [
0x48, 0x83, 0xec, 0x30, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "SUB RSP, 48 maintains alignment");
}
#[test]
fn test_sub_rsp_odd_value() {
let code = [
0x48, 0x83, 0xec, 0x18, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "SUB RSP, 24 breaks alignment");
}
#[test]
fn test_align_stack_with_and() {
let code = [
0x48, 0x83, 0xe4, 0xf0, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1008-(0x1008 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1008; emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "AND aligns stack to 16 bytes");
assert_eq!(emu.regs().rsp, 0x1000, "Stack aligned down");
}
#[test]
fn test_align_already_aligned_stack() {
let code = [
0x48, 0x83, 0xe4, 0xf0, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap();
assert_eq!(emu.regs().rsp, 0x1000, "Already aligned stack unchanged");
}
#[test]
fn test_function_prologue_alignment() {
let code = [
0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x10, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "Standard prologue results in misalignment");
}
#[test]
fn test_function_prologue_with_saved_regs() {
let code = [
0x55, 0x48, 0x89, 0xe5, 0x53, 0x48, 0x83, 0xec, 0x08, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "Prologue with saved reg misaligned");
}
#[test]
fn test_function_prologue_aligned_locals() {
let code = [
0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x08, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Aligned prologue with 8-byte adjust");
}
#[test]
fn test_push_pop_alignment_restoration() {
let code = [
0x50, 0x58, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "PUSH/POP restores alignment");
}
#[test]
fn test_sub_add_alignment_restoration() {
let code = [
0x48, 0x83, 0xec, 0x18, 0x48, 0x83, 0xc4, 0x18, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "SUB/ADD restores alignment");
}
#[test]
fn test_nested_function_alignment() {
let code = [
0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x08, 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x08, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Nested functions maintain alignment");
}
#[test]
fn test_alignment_with_parameter_passing() {
let code = [
0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03,
0x6a, 0x04, 0x6a, 0x05, 0x6a, 0x06,
0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Six parameters maintain alignment");
}
#[test]
fn test_alignment_with_odd_parameters() {
let code = [
0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03,
0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 8, "Three parameters break alignment");
}
#[test]
fn test_check_multiple_alignment_points() {
let code = [
0x50, 0x50, 0x50, 0x50, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Four pushes result in alignment");
}
#[test]
fn test_alignment_at_various_addresses() {
let code = [0xf4]; let mut emu = emu64();
emu.load_code_bytes(&code);
for addr in [0x1000, 0x2000, 0x3000, 0x4000, 0x10000, 0x100000].iter() {
emu.maps.create_map("stack_test", *addr-(*addr / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = *addr;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Address 0x{:x} is 16-byte aligned", addr);
}
}
#[test]
fn test_pushfq_popfq_alignment() {
let code = [
0x48, 0x9c, 0x48, 0x9d, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "PUSHFQ/POPFQ preserves alignment");
}
#[test]
fn test_large_stack_frame_alignment() {
let code = [
0x48, 0x81, 0xec, 0x00, 0x10, 0x00, 0x00, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x10000-(0x10000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x10000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Large allocation maintains alignment");
assert_eq!(emu.regs().rsp, 0xF000, "4KB frame allocated");
}
#[test]
fn test_alignment_after_mixed_operations() {
let code = [
0x50, 0x48, 0x83, 0xec, 0x08, 0x53, 0x48, 0x83, 0xec, 0x08, 0xf4, ];
let mut emu = emu64();
emu.load_code_bytes(&code);
emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap();
emu.regs_mut().rsp = 0x1000;
emu.run(None).unwrap();
assert_eq!(emu.regs().rsp & 0x0F, 0, "Mixed operations maintain alignment");
}