mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
implement bounds checking on all opcodes
This commit is contained in:
parent
c3f47efb07
commit
5d6977288f
2 changed files with 95 additions and 20 deletions
|
@ -257,6 +257,21 @@ PR_LeaveFunction (progs_t *pr)
|
||||||
&pr->localstack[pr->localstack_used], sizeof (pr_type_t) * c);
|
&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 OPA (*op_a)
|
||||||
#define OPB (*op_b)
|
#define OPB (*op_b)
|
||||||
#define OPC (*op_c)
|
#define OPC (*op_c)
|
||||||
|
@ -576,18 +591,27 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
case OP_STOREP_I:
|
case OP_STOREP_I:
|
||||||
case OP_STOREP_U:
|
case OP_STOREP_U:
|
||||||
case OP_STOREP_P:
|
case OP_STOREP_P:
|
||||||
//FIXME put bounds checking back
|
pointer = OPB.integer_var;
|
||||||
ptr = pr->pr_globals + 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;
|
ptr->integer_var = OPA.integer_var;
|
||||||
break;
|
break;
|
||||||
case OP_STOREP_V:
|
case OP_STOREP_V:
|
||||||
//FIXME put bounds checking back
|
pointer = OPB.integer_var;
|
||||||
ptr = pr->pr_globals + 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);
|
VectorCopy (OPA.vector_var, ptr->vector_var);
|
||||||
break;
|
break;
|
||||||
case OP_STOREP_Q:
|
case OP_STOREP_Q:
|
||||||
//FIXME put bounds checking back
|
pointer = OPB.integer_var;
|
||||||
ptr = pr->pr_globals + 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);
|
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -674,20 +698,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
case OP_LOADB_I:
|
case OP_LOADB_I:
|
||||||
case OP_LOADB_U:
|
case OP_LOADB_U:
|
||||||
case OP_LOADB_P:
|
case OP_LOADB_P:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPA.integer_var + OPB.integer_var;
|
pointer = OPA.integer_var + OPB.integer_var;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_integer);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
OPC.integer_var = ptr->integer_var;
|
OPC.integer_var = ptr->integer_var;
|
||||||
break;
|
break;
|
||||||
case OP_LOADB_V:
|
case OP_LOADB_V:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPA.integer_var + OPB.integer_var;
|
pointer = OPA.integer_var + OPB.integer_var;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_vector);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
VectorCopy (ptr->vector_var, OPC.vector_var);
|
VectorCopy (ptr->vector_var, OPC.vector_var);
|
||||||
break;
|
break;
|
||||||
case OP_LOADB_Q:
|
case OP_LOADB_Q:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPA.integer_var + OPB.integer_var;
|
pointer = OPA.integer_var + OPB.integer_var;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||||
break;
|
break;
|
||||||
|
@ -700,20 +730,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
case OP_LOADBI_I:
|
case OP_LOADBI_I:
|
||||||
case OP_LOADBI_U:
|
case OP_LOADBI_U:
|
||||||
case OP_LOADBI_P:
|
case OP_LOADBI_P:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPA.integer_var + (short) st->b;
|
pointer = OPA.integer_var + (short) st->b;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_integer);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
OPC.integer_var = ptr->integer_var;
|
OPC.integer_var = ptr->integer_var;
|
||||||
break;
|
break;
|
||||||
case OP_LOADBI_V:
|
case OP_LOADBI_V:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPA.integer_var + (short) st->b;
|
pointer = OPA.integer_var + (short) st->b;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_vector);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
VectorCopy (ptr->vector_var, OPC.vector_var);
|
VectorCopy (ptr->vector_var, OPC.vector_var);
|
||||||
break;
|
break;
|
||||||
case OP_LOADBI_Q:
|
case OP_LOADBI_Q:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPA.integer_var + (short) st->b;
|
pointer = OPA.integer_var + (short) st->b;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (ptr->quat_var, OPC.quat_var);
|
QuatCopy (ptr->quat_var, OPC.quat_var);
|
||||||
break;
|
break;
|
||||||
|
@ -736,20 +772,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
case OP_STOREB_I:
|
case OP_STOREB_I:
|
||||||
case OP_STOREB_U:
|
case OP_STOREB_U:
|
||||||
case OP_STOREB_P:
|
case OP_STOREB_P:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPB.integer_var + OPC.integer_var;
|
pointer = OPB.integer_var + OPC.integer_var;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_integer);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
ptr->integer_var = OPA.integer_var;
|
ptr->integer_var = OPA.integer_var;
|
||||||
break;
|
break;
|
||||||
case OP_STOREB_V:
|
case OP_STOREB_V:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPB.integer_var + OPC.integer_var;
|
pointer = OPB.integer_var + OPC.integer_var;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_vector);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
VectorCopy (OPA.vector_var, ptr->vector_var);
|
VectorCopy (OPA.vector_var, ptr->vector_var);
|
||||||
break;
|
break;
|
||||||
case OP_STOREB_Q:
|
case OP_STOREB_Q:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPB.integer_var + OPC.integer_var;
|
pointer = OPB.integer_var + OPC.integer_var;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||||
break;
|
break;
|
||||||
|
@ -762,20 +804,26 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
case OP_STOREBI_I:
|
case OP_STOREBI_I:
|
||||||
case OP_STOREBI_U:
|
case OP_STOREBI_U:
|
||||||
case OP_STOREBI_P:
|
case OP_STOREBI_P:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPB.integer_var + (short) st->c;
|
pointer = OPB.integer_var + (short) st->c;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_integer);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
ptr->integer_var = OPA.integer_var;
|
ptr->integer_var = OPA.integer_var;
|
||||||
break;
|
break;
|
||||||
case OP_STOREBI_V:
|
case OP_STOREBI_V:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPB.integer_var + (short) st->c;
|
pointer = OPB.integer_var + (short) st->c;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_vector);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
VectorCopy (OPA.vector_var, ptr->vector_var);
|
VectorCopy (OPA.vector_var, ptr->vector_var);
|
||||||
break;
|
break;
|
||||||
case OP_STOREBI_Q:
|
case OP_STOREBI_Q:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = OPB.integer_var + (short) st->c;
|
pointer = OPB.integer_var + (short) st->c;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_quat);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
QuatCopy (OPA.quat_var, ptr->quat_var);
|
QuatCopy (OPA.quat_var, ptr->quat_var);
|
||||||
break;
|
break;
|
||||||
|
@ -830,8 +878,10 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum)
|
||||||
st = pr->pr_statements + pr->pr_xstatement;
|
st = pr->pr_statements + pr->pr_xstatement;
|
||||||
break;
|
break;
|
||||||
case OP_JUMPB:
|
case OP_JUMPB:
|
||||||
//FIXME put bounds checking in
|
|
||||||
pointer = st->a + OPB.integer_var;
|
pointer = st->a + OPB.integer_var;
|
||||||
|
if (pr_boundscheck->int_val) {
|
||||||
|
PR_BoundsCheck (pr, pointer, ev_integer);
|
||||||
|
}
|
||||||
ptr = pr->pr_globals + pointer;
|
ptr = pr->pr_globals + pointer;
|
||||||
pointer = ptr->integer_var;
|
pointer = ptr->integer_var;
|
||||||
if (pr_boundscheck->int_val
|
if (pr_boundscheck->int_val
|
||||||
|
@ -1035,6 +1085,10 @@ op_call:
|
||||||
memmove (&OPC, &OPA, st->b * 4);
|
memmove (&OPC, &OPA, st->b * 4);
|
||||||
break;
|
break;
|
||||||
case OP_MOVEP:
|
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,
|
memmove (pr->pr_globals + OPC.integer_var,
|
||||||
pr->pr_globals + OPA.integer_var,
|
pr->pr_globals + OPA.integer_var,
|
||||||
OPB.uinteger_var * 4);
|
OPB.uinteger_var * 4);
|
||||||
|
|
|
@ -1213,7 +1213,8 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (operand >= pr->progs->numglobals) {
|
if (operand + (unsigned) pr_type_size[type]
|
||||||
|
> pr->progs->numglobals) {
|
||||||
msg = "out of bounds global index";
|
msg = "out of bounds global index";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1226,6 +1227,22 @@ error:
|
||||||
(long)(st - pr->pr_statements), op->opname);
|
(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
|
int
|
||||||
PR_Check_Opcodes (progs_t *pr)
|
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_b, st->b);
|
||||||
check_global (pr, st, op, op->type_c, st->c);
|
check_global (pr, st, op, op->type_c, st->c);
|
||||||
break;
|
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:
|
default:
|
||||||
check_global (pr, st, op, op->type_a, st->a);
|
check_global (pr, st, op, op->type_a, st->a);
|
||||||
check_global (pr, st, op, op->type_b, st->b);
|
check_global (pr, st, op, op->type_b, st->b);
|
||||||
|
|
Loading…
Reference in a new issue