}
static int fuzz_read(
- unsigned int seg,
+ enum x86_segment seg,
unsigned long offset,
void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
+ /* Reads expected for all user and system segments. */
+ assert(is_x86_user_segment(seg) || is_x86_system_segment(seg));
+
return data_read(ctxt, "read", p_data, bytes);
}
}
static int fuzz_insn_fetch(
- unsigned int seg,
+ enum x86_segment seg,
unsigned long offset,
void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
+ assert(seg == x86_seg_cs);
+
/*
* Zero-length instruction fetches are made at the destination of jumps,
* to perform segmentation checks. No data needs returning.
unsigned long *reps,
struct x86_emulate_ctxt *ctxt)
{
+ assert(dst_seg == x86_seg_es);
+
return _fuzz_rep_read(ctxt, "rep_ins", reps);
}
unsigned long *reps,
struct x86_emulate_ctxt *ctxt)
{
+ assert(is_x86_user_segment(src_seg));
+ assert(dst_seg == x86_seg_es);
+
return _fuzz_rep_read(ctxt, "rep_movs", reps);
}
unsigned long *reps,
struct x86_emulate_ctxt *ctxt)
{
+ assert(is_x86_user_segment(src_seg));
+
return _fuzz_rep_write(ctxt, "rep_outs", reps);
}
unsigned long *reps,
struct x86_emulate_ctxt *ctxt)
{
+ /*
+ * STOS itself may only have an %es segment, but the stos() hook is reused
+ * for CLZERO.
+ */
+ assert(is_x86_user_segment(seg));
+
return _fuzz_rep_write(ctxt, "rep_stos", reps);
}
static int fuzz_write(
- unsigned int seg,
+ enum x86_segment seg,
unsigned long offset,
void *p_data,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
+ /* Writes not expected for any system segments. */
+ assert(is_x86_user_segment(seg));
+
return maybe_fail(ctxt, "write", true);
}
static int fuzz_cmpxchg(
- unsigned int seg,
+ enum x86_segment seg,
unsigned long offset,
void *old,
void *new,
unsigned int bytes,
struct x86_emulate_ctxt *ctxt)
{
+ /*
+ * Cmpxchg expected for user segments, and setting accessed/busy bits in
+ * GDT/LDT enties, but not expected for any IDT or TR accesses.
+ */
+ assert(is_x86_user_segment(seg) ||
+ seg == x86_seg_gdtr || seg == x86_seg_ldtr);
+
return maybe_fail(ctxt, "cmpxchg", true);
}
unsigned long offset,
struct x86_emulate_ctxt *ctxt)
{
+ /* invlpg(), unlike all other hooks, may be called with x86_seg_none. */
+ assert(is_x86_user_segment(seg) || seg == x86_seg_none);
+
return maybe_fail(ctxt, "invlpg", false);
}
const struct fuzz_state *s = ctxt->data;
const struct fuzz_corpus *c = s->corpus;
- if ( seg >= SEG_NUM )
- return X86EMUL_UNHANDLEABLE;
+ assert(is_x86_user_segment(seg) || is_x86_system_segment(seg));
*reg = c->segments[seg];
struct fuzz_corpus *c = s->corpus;
int rc;
- if ( seg >= SEG_NUM )
- return X86EMUL_UNHANDLEABLE;
+ assert(is_x86_user_segment(seg) || is_x86_system_segment(seg));
rc = maybe_fail(ctxt, "write_segment", true);