From d8d06031d207052580ef4c92799465192a9dff8b Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Wed, 30 Oct 2024 08:55:28 -0400 Subject: [PATCH] Support STOREP_* with offset. --- prvm_edict.c | 18 ++++++++++++------ prvm_execprogram.h | 43 +++++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/prvm_edict.c b/prvm_edict.c index d219d0b6..024ac639 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -1458,9 +1458,9 @@ qbool PRVM_ED_CallSpawnFunction(prvm_prog_t *prog, prvm_edict_t *ent, const char } else { - + Con_DPrint("No spawn function for:\n"); - if (developer.integer > 0) // don't confuse non-developers with errors + if (developer.integer > 0) // don't confuse non-developers with errors PRVM_ED_Print(prog, ent, NULL); PRVM_ED_Free (prog, ent); @@ -1567,7 +1567,7 @@ void PRVM_ED_LoadFromFile (prvm_prog_t *prog, const char *data) if(!PRVM_ED_CallSpawnFunction(prog, ent, data, start)) continue; - + PRVM_ED_CallPostspawnFunction(prog, ent); spawned++; @@ -2445,17 +2445,23 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data case OP_STOREP_FLD: case OP_STOREP_S: case OP_STOREP_FNC: + case OP_STOREP_V: if (c) //Spike -- DP is alergic to pointers in QC. Try to avoid too many nasty surprises. Con_DPrintf("%s: storep-with-offset is not permitted in %s\n", __func__, prog->name); - //fallthrough + if (a >= prog->progs_numglobals || b >= prog->progs_numglobals || c >= prog->progs_numglobals) + prog->error_cmd("%s: out of bounds global index (statement %d) in %s", __func__, i, prog->name); + prog->statements[i].op = op; + prog->statements[i].operand[0] = remapglobal(a); + prog->statements[i].operand[1] = remapglobal(b); + prog->statements[i].operand[2] = remapglobal(c); + break; case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: case OP_STORE_S: case OP_STORE_FNC: - case OP_STATE: - case OP_STOREP_V: case OP_STORE_V: + case OP_STATE: if (a >= prog->progs_numglobals || b >= prog->progs_numglobals) prog->error_cmd("%s: out of bounds global index (statement %d) in %s", __func__, i, prog->name); prog->statements[i].op = op; diff --git a/prvm_execprogram.h b/prvm_execprogram.h index 68d0a673..ce532edb 100644 --- a/prvm_execprogram.h +++ b/prvm_execprogram.h @@ -1,6 +1,6 @@ extern cvar_t prvm_garbagecollection_enable; int i; -prvm_uint_t addr; +prvm_uint_t ofs, addr; // NEED to reset startst after calling this! startst may or may not be clobbered! #define ADVANCE_PROFILE_BEFORE_JUMP() \ prog->xfunction->profile += (st - startst); \ @@ -479,59 +479,61 @@ prvm_uint_t addr; HANDLE_OPCODE(OP_STOREP_ENT): HANDLE_OPCODE(OP_STOREP_FLD): // integers HANDLE_OPCODE(OP_STOREP_FNC): // pointers - if ((addr = (prvm_uint_t)OPB->_int - cached_vmentity1start) < cached_entityfieldsarea_entityfields) + ofs = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int; + if ((addr = ofs - cached_vmentity1start) < cached_entityfieldsarea_entityfields) { // OK entity write. ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + addr); } - else if ((addr = (prvm_uint_t)OPB->_int - cached_vmglobal1) < cached_vmglobals_1) + else if ((addr = ofs - cached_vmglobal1) < cached_vmglobals_1) { // OK global write. ptr = (prvm_eval_t *)(global1 + addr); } - else if ((prvm_uint_t)OPB->_int - cached_vmentity0start < cached_entityfields) + else if ((addr = ofs - cached_vmentity0start) < cached_entityfields) { if (!cached_allowworldwrites) { PRE_ERROR(); - VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int); + VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, addr)->s_name), OPB->_int, OPC->_int); // Perform entity write anyway. } - ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); + ptr = (prvm_eval_t *)(cached_edictsfields + addr); } else { PRE_ERROR(); - prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int); + prog->error_cmd("%s attempted to write to an out of bounds address %u+%i", prog->name, (unsigned int)OPB->_int, OPC->_int); goto cleanup; } ptr->_int = OPA->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_STOREP_S): - if ((addr = (prvm_uint_t)OPB->_int - cached_vmentity1start) < cached_entityfieldsarea_entityfields) + ofs = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int; + if ((addr = ofs - cached_vmentity1start) < cached_entityfieldsarea_entityfields) { // OK entity write. ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + addr); } - else if ((addr = (prvm_uint_t)OPB->_int - cached_vmglobal1) < cached_vmglobals_1) + else if ((addr = ofs - cached_vmglobal1) < cached_vmglobals_1) { // OK global write. ptr = (prvm_eval_t *)(global1 + addr); } - else if ((prvm_uint_t)OPB->_int - cached_vmentity0start < cached_entityfields) + else if ((addr = ofs - cached_vmentity0start) < cached_entityfields) { if (!cached_allowworldwrites) { PRE_ERROR(); - VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int); + VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, addr)->s_name), OPB->_int, OPC->_int); // Perform entity write anyway. } - ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); + ptr = (prvm_eval_t *)(cached_edictsfields + addr); } else { PRE_ERROR(); - prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int); + prog->error_cmd("%s attempted to write to an out of bounds address %u+%i", prog->name, (unsigned int)OPB->_int, OPC->_int); goto cleanup; } // refresh the garbage collection on the string - this guards @@ -543,30 +545,31 @@ prvm_uint_t addr; ptr->_int = OPA->_int; DISPATCH_OPCODE(); HANDLE_OPCODE(OP_STOREP_V): - if ((addr = (prvm_uint_t)OPB->_int - cached_vmentity1start) < cached_entityfieldsarea_entityfields_2) + ofs = (prvm_uint_t)OPB->_int + (prvm_uint_t)OPC->_int; + if ((addr = ofs - cached_vmentity1start) < cached_entityfieldsarea_entityfields_2) { // OK entity write. ptr = (prvm_eval_t *)(cached_edictsfields_entity1 + addr); } - else if ((addr = (prvm_uint_t)OPB->_int - cached_vmglobal1) < cached_vmglobals_3) + else if ((addr = ofs - cached_vmglobal1) < cached_vmglobals_3) { // OK global write. - ptr = (prvm_eval_t *)(global1 + OPB->_int); + ptr = (prvm_eval_t *)(global1 + addr); } - else if ((prvm_uint_t)OPB->_int - cached_vmentity0start < cached_entityfields_2) + else if ((addr = ofs - cached_vmentity0start) < cached_entityfields_2) { if (!cached_allowworldwrites) { PRE_ERROR(); - VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int); + VM_Warning(prog, "Attempted assignment to world.%s (edictnum 0 field %i+%i)\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, addr)->s_name), OPB->_int, OPC->_int); // Perform entity write anyway. } - ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); + ptr = (prvm_eval_t *)(cached_edictsfields + addr); } else { PRE_ERROR(); - prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int); + prog->error_cmd("%s attempted to write to an out of bounds address %u+%i", prog->name, (unsigned int)OPB->_int, OPC->_int); goto cleanup; } ptr->ivector[0] = OPA->ivector[0]; -- 2.39.2