implement bounds checking on all opcodes

This commit is contained in:
Bill Currie 2010-01-13 06:19:50 +00:00 committed by Jeff Teunissen
parent c3f47efb07
commit 5d6977288f
2 changed files with 95 additions and 20 deletions

View File

@ -257,6 +257,21 @@ PR_LeaveFunction (progs_t *pr)
&pr->localstack[pr->localstack_used], sizeof (pr_type_t) * c);
}
static void
PR_BoundsCheckSize (progs_t *pr, int addr, unsigned size)
{
if (addr < 0 || addr >= pr->globals_size
|| size > (unsigned) (pr->globals_size - addr))
PR_RunError (pr, "invalid memory access: %d (0 to %d-%d)", addr,
pr->globals_size, size);
}
static void
PR_BoundsCheck (progs_t *pr, int addr, etype_t type)
{
PR_BoundsCheckSize (pr, addr, pr_type_size[type]);
}
#define OPA (*op_a)
#define OPB (*op_b)
#define OPC (*op_c)
@ -576,18 +591,27 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
case OP_STOREP_I:
case OP_STOREP_U:
case OP_STOREP_P:
//FIXME put bounds checking back
ptr = pr->pr_globals + OPB.integer_var;
pointer = OPB.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_integer);
}
ptr = pr->pr_globals + pointer;
ptr->integer_var = OPA.integer_var;
break;
case OP_STOREP_V:
//FIXME put bounds checking back
ptr = pr->pr_globals + OPB.integer_var;
pointer = OPB.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_vector);
}
ptr = pr->pr_globals + pointer;
VectorCopy (OPA.vector_var, ptr->vector_var);
break;
case OP_STOREP_Q:
//FIXME put bounds checking back
ptr = pr->pr_globals + OPB.integer_var;
pointer = OPB.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_quat);
}
ptr = pr->pr_globals + pointer;
QuatCopy (OPA.quat_var, ptr->quat_var);
break;
@ -674,20 +698,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
case OP_LOADB_I:
case OP_LOADB_U:
case OP_LOADB_P:
//FIXME put bounds checking in
pointer = OPA.integer_var + OPB.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_integer);
}
ptr = pr->pr_globals + pointer;
OPC.integer_var = ptr->integer_var;
break;
case OP_LOADB_V:
//FIXME put bounds checking in
pointer = OPA.integer_var + OPB.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_vector);
}
ptr = pr->pr_globals + pointer;
VectorCopy (ptr->vector_var, OPC.vector_var);
break;
case OP_LOADB_Q:
//FIXME put bounds checking in
pointer = OPA.integer_var + OPB.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_quat);
}
ptr = pr->pr_globals + pointer;
QuatCopy (ptr->quat_var, OPC.quat_var);
break;
@ -700,20 +730,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
case OP_LOADBI_I:
case OP_LOADBI_U:
case OP_LOADBI_P:
//FIXME put bounds checking in
pointer = OPA.integer_var + (short) st->b;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_integer);
}
ptr = pr->pr_globals + pointer;
OPC.integer_var = ptr->integer_var;
break;
case OP_LOADBI_V:
//FIXME put bounds checking in
pointer = OPA.integer_var + (short) st->b;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_vector);
}
ptr = pr->pr_globals + pointer;
VectorCopy (ptr->vector_var, OPC.vector_var);
break;
case OP_LOADBI_Q:
//FIXME put bounds checking in
pointer = OPA.integer_var + (short) st->b;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_quat);
}
ptr = pr->pr_globals + pointer;
QuatCopy (ptr->quat_var, OPC.quat_var);
break;
@ -736,20 +772,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
case OP_STOREB_I:
case OP_STOREB_U:
case OP_STOREB_P:
//FIXME put bounds checking in
pointer = OPB.integer_var + OPC.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_integer);
}
ptr = pr->pr_globals + pointer;
ptr->integer_var = OPA.integer_var;
break;
case OP_STOREB_V:
//FIXME put bounds checking in
pointer = OPB.integer_var + OPC.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_vector);
}
ptr = pr->pr_globals + pointer;
VectorCopy (OPA.vector_var, ptr->vector_var);
break;
case OP_STOREB_Q:
//FIXME put bounds checking in
pointer = OPB.integer_var + OPC.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_quat);
}
ptr = pr->pr_globals + pointer;
QuatCopy (OPA.quat_var, ptr->quat_var);
break;
@ -762,20 +804,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
case OP_STOREBI_I:
case OP_STOREBI_U:
case OP_STOREBI_P:
//FIXME put bounds checking in
pointer = OPB.integer_var + (short) st->c;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_integer);
}
ptr = pr->pr_globals + pointer;
ptr->integer_var = OPA.integer_var;
break;
case OP_STOREBI_V:
//FIXME put bounds checking in
pointer = OPB.integer_var + (short) st->c;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_vector);
}
ptr = pr->pr_globals + pointer;
VectorCopy (OPA.vector_var, ptr->vector_var);
break;
case OP_STOREBI_Q:
//FIXME put bounds checking in
pointer = OPB.integer_var + (short) st->c;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_quat);
}
ptr = pr->pr_globals + pointer;
QuatCopy (OPA.quat_var, ptr->quat_var);
break;
@ -830,8 +878,10 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
st = pr->pr_statements + pr->pr_xstatement;
break;
case OP_JUMPB:
//FIXME put bounds checking in
pointer = st->a + OPB.integer_var;
if (pr_boundscheck->int_val) {
PR_BoundsCheck (pr, pointer, ev_integer);
}
ptr = pr->pr_globals + pointer;
pointer = ptr->integer_var;
if (pr_boundscheck->int_val
@ -1035,6 +1085,10 @@ op_call:
memmove (&OPC, &OPA, st->b * 4);
break;
case OP_MOVEP:
if (pr_boundscheck->int_val) {
PR_BoundsCheckSize (pr, OPC.integer_var, OPB.uinteger_var);
PR_BoundsCheckSize (pr, OPA.integer_var, OPB.uinteger_var);
}
memmove (pr->pr_globals + OPC.integer_var,
pr->pr_globals + OPA.integer_var,
OPB.uinteger_var * 4);

View File

@ -1213,7 +1213,8 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
}
break;
default:
if (operand >= pr->progs->numglobals) {
if (operand + (unsigned) pr_type_size[type]
> pr->progs->numglobals) {
msg = "out of bounds global index";
goto error;
}
@ -1226,6 +1227,22 @@ error:
(long)(st - pr->pr_statements), op->opname);
}
static inline void
check_global_size (progs_t *pr, dstatement_t *st, opcode_t *op,
unsigned short size, unsigned short operand)
{
const char *msg;
if (operand + size > pr->progs->numglobals) {
msg = "out of bounds global index";
goto error;
}
return;
error:
PR_PrintStatement (pr, st, 0);
PR_Error (pr, "PR_Check_Opcodes: %s (statement %ld: %s)", msg,
(long)(st - pr->pr_statements), op->opname);
}
int
PR_Check_Opcodes (progs_t *pr)
{
@ -1300,6 +1317,10 @@ PR_Check_Opcodes (progs_t *pr)
check_global (pr, st, op, op->type_b, st->b);
check_global (pr, st, op, op->type_c, st->c);
break;
case OP_MOVE:
check_global_size (pr, st, op, st->b, st->a);
check_global_size (pr, st, op, st->b, st->c);
break;
default:
check_global (pr, st, op, op->type_a, st->a);
check_global (pr, st, op, op->type_b, st->b);