]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
Support STOREP_* with offset.
authorRudolf Polzer <divVerent@gmail.com>
Wed, 30 Oct 2024 12:55:28 +0000 (08:55 -0400)
committerdivVerent <divVerent@gmail.com>
Tue, 12 Nov 2024 17:49:21 +0000 (12:49 -0500)
prvm_edict.c
prvm_execprogram.h

index d219d0b698b1f07a49d6759333df319bc27b0da0..024ac639ffea8b681c72cf9011b82793a951f648 100644 (file)
@@ -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;
index 68d0a673a1988781786e6eec4b4c5d6245adfa1f..ce532edbc2a7077d01549628818c8b139a131aaa 100644 (file)
@@ -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];