x86emul: avoid undefined behavior when dealing with 10-byte FPU operands Accessing an 8-byte (or perhaps just 4-byte in the test harness when built as 32-bit app) field to read/write 10 bytes (leveraging the successive field) is a latent bug, as the compiler could copy things around. Use the 32 bytes large SSE/AVX slot instead. Signed-off-by: Jan Beulich --- The presence of the !op->write checks implies a logical (but not functional) dependency on the patch making ops->write (and ->cmpxchg) optional. Without that patch they're just dead code. Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -3882,15 +3882,19 @@ x86_emulate( dst.bytes = 4; break; case 5: /* fld m80fp */ - if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val, + if ( (rc = ops->read(ea.mem.seg, ea.mem.off, mmvalp, 10, ctxt)) != X86EMUL_OKAY ) goto done; - emulate_fpu_insn_memsrc("fldt", src.val); + emulate_fpu_insn_memsrc("fldt", *mmvalp); dst.type = OP_NONE; break; case 7: /* fstp m80fp */ - emulate_fpu_insn_memdst("fstpt", dst.val); - dst.bytes = 10; + fail_if(!ops->write); + emulate_fpu_insn_memdst("fstpt", *mmvalp); + if ( (rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp, + 10, ctxt)) != X86EMUL_OKAY ) + goto done; + dst.type = OP_NONE; break; default: generate_exception_if(true, EXC_UD); @@ -4099,10 +4103,10 @@ x86_emulate( dst.bytes = 2; break; case 4: /* fbld m80dec */ - if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val, + if ( (rc = ops->read(ea.mem.seg, ea.mem.off, mmvalp, 10, ctxt)) != X86EMUL_OKAY ) goto done; - emulate_fpu_insn_memsrc("fbld", src.val); + emulate_fpu_insn_memsrc("fbld", *mmvalp); dst.type = OP_NONE; break; case 5: /* fild m64i */ @@ -4113,8 +4117,12 @@ x86_emulate( dst.type = OP_NONE; break; case 6: /* fbstp packed bcd */ - emulate_fpu_insn_memdst("fbstp", dst.val); - dst.bytes = 10; + fail_if(!ops->write); + emulate_fpu_insn_memdst("fbstp", *mmvalp); + if ( (rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp, + 10, ctxt)) != X86EMUL_OKAY ) + goto done; + dst.type = OP_NONE; break; case 7: /* fistp m64i */ emulate_fpu_insn_memdst("fistpll", dst.val);