https://bugs.kde.org/show_bug.cgi?id=517848
Bug ID: 517848
Summary: x86-64: incorrect execution of instructions with REX
prefixes in invalid positions
Classification: Developer tools
Product: valgrind
Version First 3.27 GIT
Reported In:
Platform: openSUSE
OS: Linux
Status: REPORTED
Severity: normal
Priority: NOR
Component: vex
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
SUMMARY
I believe to have discovered a bug where libVEX is not handling ignored x86-64
REX prefixes correctly. When another prefix follows a REX prefix, the REX
prefix must be ignored. This is specified by the AMD (Volume 1, Section 3.5.2)
and Intel Manuals (Volume 2, Section 2.2.1).
Currently REX prefixes in ignored positions are not ignored by libVEX. This
means that for example 4C6601C8 (REX + DATA16 + instr) is executed as having a
REX prefix (and thus performing a 64-bit operation), instead of as having only
a DATA16 prefix (and thus performing a 16-bit operation).
STEPS TO REPRODUCE
Compile the following program and execute it in Valgrind:
#include <stdio.h>
#include <stdint.h>
int main() {
uint64_t a = 0x11223344;
uint64_t b = 0x55667788;
uint64_t c = 0x99aabbcc;
asm volatile (
"mov %[a], %%rax\n\t"
"mov %[b], %%rcx\n\t"
"mov %[c], %%r9\n\t"
".byte 0x4C, 0x66, 0x01, 0xC8\n\t"
"mov %%rax, %[a]\n\t"
"mov %%rcx, %[b]\n\t"
"mov %%r9, %[c]\n\t"
: [a] "+r" (a), [b] "+r" (b), [c] "+r" (c)
:
: "rax", "rcx", "r9"
);
printf("a = 0x%llx\n", (unsigned long long)a);
printf("b = 0x%llx\n", (unsigned long long)b);
printf("c = 0x%llx\n", (unsigned long long)c);
return 0;
}
(another fun variation is 444801C8, where valgrind takes the logical OR of both
REX prefixes instead of the last)
OBSERVED RESULT
Executing with Valgrind results in:
a = 0xaaccef10
b = 0x55667788
c = 0x99aabbcc
EXPECTED RESULT
Executing normally results in:
a = 0x1122aacc
b = 0x55667788
c = 0x99aabbcc
SOFTWARE/OS VERSIONS
Operating System: openSUSE Tumbleweed 20260307
KDE Plasma Version: 6.6.2
KDE Frameworks Version: 6.23.0
Qt Version: 6.10.2
Kernel Version: 6.19.5-2-default (64-bit)
ADDITIONAL INFORMATION
I am happy to try to fix this and provide a patch. I see two possible
approaches:
1.) Rejecting instructions with REX prefixes in ignored positions
2.) Correctly handling REX prefixes in ignored positions
Having looked at the code in VEX/priv/guest_amd64_toIR.c both approaches will
result in fairly small patches.
I would typically advocate for correctly handling every instruction, but given
that Valgrind also rejects other unexpected combinations of prefixes (like
multiple segment overrides or both F2 and F3), rejecting instructions with
ignored REX prefixes might also make sense.
I am interested in hearing your thoughts on the best approach before I start
working on a patch.
--
You are receiving this mail because:
You are watching all bug changes.