From 0d33dacc37f4ae1e21c60fe41796a5d90c96e3eb Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 13 Mar 2024 18:36:19 -0700 Subject: [PATCH] unittests/ASM: Implements a unit test for #3478 This unit test recreates the error condition that #3478 causes. With a string operation that is a backwards copy then the optimization will read past the end of the page and result in a crash. Seemingly only happens with backwards string operations, but test forward and backward in this test. --- .../ASM/FEX_bugs/repeat_stringops_crash.asm | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 unittests/ASM/FEX_bugs/repeat_stringops_crash.asm diff --git a/unittests/ASM/FEX_bugs/repeat_stringops_crash.asm b/unittests/ASM/FEX_bugs/repeat_stringops_crash.asm new file mode 100644 index 0000000000..5ebdde8cf7 --- /dev/null +++ b/unittests/ASM/FEX_bugs/repeat_stringops_crash.asm @@ -0,0 +1,65 @@ +%ifdef CONFIG +{ + "MemoryRegions": { + "0xf0000000": "4096", + "0xf1000000": "4096" + } +} +%endif + +; FEX-Emu had a bug where a backwards repeating string operation would read past the end of a mapped page. +; This was encountered in https://github.com/FEX-Emu/FEX/pull/3478. +; To ensure we don't read past a page with `rep stos` and `rep movs`, map two disparate pages and copy the entire page. +; If FEX tries reading past the ends of either then it will fault. +%macro do_rep_op 2 + jmp %%1 + %%1: + + cld + mov rax, r13 + mov rdi, r14 + mov rsi, r15 + mov rcx, (4096 / %2) + rep %1 +%endmacro + +%macro do_backward_rep_op 2 + jmp %%1 + %%1: + + std + mov rax, r13 + mov rdi, r14 + mov rsi, r15 + add rdi, (4096 - %2) + add rsi, (4096 - %2) + mov rcx, (4096 / %2) + rep %1 +%endmacro + +mov r15, 0xf000_0000 +mov r14, 0xf100_0000 +mov r13, 0x41424344454647 + +do_rep_op stosb, 1 +do_rep_op stosw, 2 +do_rep_op stosd, 4 +do_rep_op stosq, 8 + +do_backward_rep_op stosb, 1 +do_backward_rep_op stosw, 2 +do_backward_rep_op stosd, 4 +do_backward_rep_op stosq, 8 + +do_rep_op movsb, 1 +do_rep_op movsw, 2 +do_rep_op movsd, 4 +do_rep_op movsq, 8 + +do_backward_rep_op movsb, 1 +do_backward_rep_op movsw, 2 +do_backward_rep_op movsd, 4 +do_backward_rep_op movsq, 8 + +hlt +