Skip to content

Commit 58e50aa

Browse files
hsqStephenZhangqmonnet
authored andcommitted
fix: use is_reg for devisor in emit_muldivmod
Signed-off-by: hsqStephenZhang <stephenzhang666666@gmail.com>
1 parent 2f99865 commit 58e50aa

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

src/jit.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,9 @@ impl JitCompiler {
433433
if dst != RDX {
434434
self.emit_push(mem, RDX);
435435
}
436-
if imm != 0 {
436+
437+
// Load the divisor into RCX.
438+
if !is_reg {
437439
self.emit_load_imm(mem, RCX, imm as i64);
438440
} else {
439441
self.emit_mov(mem, src, RCX);

tests/ubpf_jit_x86_64.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,65 @@ fn test_jit_mod_by_zero_reg() {
877877
}
878878
}
879879

880+
#[test]
881+
fn test_jit_div_reg_with_nonzero_imm() {
882+
// This test checks the fix for using is_reg instead of imm != 0
883+
// when deciding whether to load an immediate or move a register for the divisor.
884+
// Hand-crafted bytecode with DIV (register mode) but non-zero immediate field.
885+
// The immediate should be ignored for register operations.
886+
#[rustfmt::skip]
887+
let prog = &[
888+
// mov r0, 100
889+
0xb7, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
890+
// mov r1, 5
891+
0xb7, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
892+
// div r0, r1 (but with non-zero immediate field 0x99999999)
893+
// Opcode 0x3f = DIV64 | BPF_X (register mode)
894+
0x3f, 0x10, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99,
895+
// exit
896+
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
897+
];
898+
899+
let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
900+
#[cfg(not(feature = "std"))]
901+
let mut exec_mem = alloc_exec_memory();
902+
#[cfg(not(feature = "std"))]
903+
vm.set_jit_exec_memory(&mut exec_mem).unwrap();
904+
vm.jit_compile().unwrap();
905+
unsafe {
906+
// Should divide 100 by r1 (5), not by the immediate (0x99999999)
907+
assert_eq!(vm.execute_program_jit().unwrap(), 0x14); // 100 / 5 = 20 (0x14)
908+
}
909+
}
910+
911+
#[test]
912+
fn test_jit_mod_reg_with_nonzero_imm() {
913+
// Companion test for modulo operation with non-zero immediate in register mode
914+
#[rustfmt::skip]
915+
let prog = &[
916+
// mov r0, 107
917+
0xb7, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00,
918+
// mov r1, 5
919+
0xb7, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
920+
// mod r0, r1 (but with non-zero immediate field 0x88888888)
921+
// Opcode 0x9f = MOD64 | BPF_X (register mode)
922+
0x9f, 0x10, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88,
923+
// exit
924+
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
925+
];
926+
927+
let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
928+
#[cfg(not(feature = "std"))]
929+
let mut exec_mem = alloc_exec_memory();
930+
#[cfg(not(feature = "std"))]
931+
vm.set_jit_exec_memory(&mut exec_mem).unwrap();
932+
vm.jit_compile().unwrap();
933+
unsafe {
934+
// Should modulo 107 by r1 (5), not by the immediate (0x88888888)
935+
assert_eq!(vm.execute_program_jit().unwrap(), 0x2); // 107 % 5 = 2
936+
}
937+
}
938+
880939
// TODO SKIP: JIT disabled for this testcase (stack oob check not implemented)
881940
// #[test]
882941
// #[should_panic(expected = "Error: out of bounds memory store (insn #1)")]

0 commit comments

Comments
 (0)