Fix some qcc bugs with large structs (reported by qqshka).

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6270 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2022-06-19 15:18:14 +00:00
parent 06038d496e
commit c715171416
3 changed files with 41 additions and 15 deletions

View File

@ -1059,7 +1059,7 @@ reeval:
break;
case OP_LOADA_I64:
i = st->a + OPB->_int;
if ((size_t)i >= (size_t)(current_progstate->globals_bytes>>2))
if ((size_t)i >= (size_t)(current_progstate->globals_bytes>>2)-1u)
{
QCFAULT(&progfuncs->funcs, "bad array read in %s (index %i)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), OPB->_int);
}

View File

@ -7063,12 +7063,12 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
case REF_ARRAY:
if (!arglist[i]->index.cast || QCC_SRef_EvalConst(arglist[i]->index))
break; //no problem
if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_V]))
if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]))
{
copyop[2] = OP_LOADA_V;
// copyop[1] = OP_LOADA_I64;
copyop[1] = OP_LOADA_I64;
copyop[0] = OP_LOADA_F;
copyop_idx = -1;
copyop_idx = 0; //offset the base ref
copyop_index = arglist[i]->index;
copyop_index = QCC_SupplyConversion(copyop_index, ev_integer, true);
sref = arglist[i]->base;
@ -7206,30 +7206,30 @@ QCC_sref_t QCC_PR_GenerateFunctionCallRef (QCC_sref_t newself, QCC_sref_t func,
{
if (ofs%3)
parm--;
if (parm+ofs/3>=MAX_PARMS)
if (parm>=MAX_PARMS)
{
fparm = extra_parms[parm+ofs/3 - MAX_PARMS];
fparm = extra_parms[parm - MAX_PARMS];
if (!fparm.cast)
{
char name[128];
QC_snprintfz(name, sizeof(name), "$parm%u", parm+ofs/3);
fparm = extra_parms[parm+ofs/3 - MAX_PARMS] = QCC_PR_GetSRef(type_vector, name, NULL, true, 0, GDF_STRIP);
QC_snprintfz(name, sizeof(name), "$parm%u", parm);
fparm = extra_parms[parm - MAX_PARMS] = QCC_PR_GetSRef(type_vector, name, NULL, true, 0, GDF_STRIP);
}
else
QCC_ForceUnFreeDef(fparm.sym);
}
else
{
fparm.sym = &def_parms[parm+ofs/3];
fparm.sym = &def_parms[parm];
fparm.cast = type_vector;
QCC_ForceUnFreeDef(fparm.sym);
}
fparm.ofs = ofs;
// if (!fparm.ofs)
// {
fparm.ofs = ofs%3;
if (!fparm.ofs)
{
args[parm].firststatement = numstatements;
args[parm].ref = fparm;
// }
}
parm++;
if (ofs+asz == arglist[i]->cast->size)
@ -11293,6 +11293,13 @@ QCC_sref_t QCC_LoadFromArray(QCC_sref_t base, QCC_sref_t index, QCC_type_t *t, p
base.ofs += 3;
r.ofs+=3;
}
else if (t->size - i >= 2 && QCC_OPCodeValid(&pr_opcodes[OP_LOADA_I64]))
{
QCC_PR_SimpleStatement(&pr_opcodes[OP_LOADA_I64], base, index, r, false);
i+=2;
base.ofs += 2;
r.ofs+=2;
}
else
{
QCC_PR_SimpleStatement(&pr_opcodes[OP_LOADA_I], base, index, r, false);
@ -15702,6 +15709,11 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_def_t *def, QCC_type_t *typ
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_V], extra_parms[p - MAX_PARMS], parm, NULL));
parm.ofs+=3;
}
else if (type->params[u].type->size-o*3 == 2 && QCC_OPCodeValid(&pr_opcodes[OP_STORE_I64]))
{
QCC_FreeTemp(QCC_PR_Statement (&pr_opcodes[OP_STORE_I64], extra_parms[p - MAX_PARMS], parm, NULL));
parm.ofs+=2;
}
else if (type->params[u].type->size-o*3 == 2)
{
QCC_sref_t t = extra_parms[p - MAX_PARMS];
@ -17149,6 +17161,20 @@ finalnotconst:
def.ofs += 3;
rhs.ofs += 3;
}
else if (type->size - i >= 2)
{
rhs.cast = def.cast = type_vector;
if (type->size - i == 2)
{
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_I64], nullsource?QCC_MakeVectorConst(0,0,0):rhs, def, NULL, STFL_PRESERVEB));
return ret;
}
else
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_I64], nullsource?QCC_MakeVectorConst(0,0,0):rhs, def, NULL, STFL_PRESERVEA|STFL_PRESERVEB));
i+=2;
def.ofs += 2;
rhs.ofs += 2;
}
else
{
if (nullsource)

View File

@ -11714,7 +11714,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"SetListener", PF_Fixme, 0, 0, 0, 351, D("void(vector origin, vector forward, vector right, vector up, optional float reverbtype)", "Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default. For reverbtype, see setup_reverb or treat as 'underwater'.")},// (EXT_CSQC)
{"setup_reverb", PF_Fixme, 0, 0, 0, 0, D("typedef struct {\n\tfloat flDensity;\n\tfloat flDiffusion;\n\tfloat flGain;\n\tfloat flGainHF;\n\tfloat flGainLF;\n\tfloat flDecayTime;\n\tfloat flDecayHFRatio;\n\tfloat flDecayLFRatio;\n\tfloat flReflectionsGain;\n\tfloat flReflectionsDelay;\n\tvector flReflectionsPan;\n\tfloat flLateReverbGain;\n\tfloat flLateReverbDelay;\n\tvector flLateReverbPan;\n\tfloat flEchoTime;\n\tfloat flEchoDepth;\n\tfloat flModulationTime;\n\tfloat flModulationDepth;\n\tfloat flAirAbsorptionGainHF;\n\tfloat flHFReference;\n\tfloat flLFReference;\n\tfloat flRoomRolloffFactor;\n\tint iDecayHFLimit;\n} reverbinfo_t;\nvoid(float reverbslot, reverbinfo_t *reverbinfo, int sizeofreverinfo_t)", "Reconfigures a reverb slot for weird effects. Slot 0 is reserved for no effects. Slot 1 is reserved for underwater effects. Reserved slots will be reinitialised on snd_restart, but can otherwise be changed. These reverb slots can be activated with SetListener. Note that reverb will currently only work when using OpenAL.")},
{"registercommand", PF_sv_registercommand,0,0, 0, 352, D("void(string cmdname)", "Register the given console command, for easy console use.\nConsole commands that are later used will invoke CSQC_ConsoleCommand/m_consolecommand/ConsoleCmd according to module.")},//(EXT_CSQC)
{"wasfreed", PF_WasFreed,0, 0, 0, 353, D("float(entity ent)", "Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust.")},//(EXT_CSQC) (should be availabe on server too)
{"wasfreed", PF_WasFreed,0, 0, 0, 353, D("float(entity ent)", "Quickly check to see if the entity is currently free. This function is only valid during the half-second non-reuse window, after that it may give bad results. Try one second to make it more robust.")},//(EXT_CSQC) (should be availabe on server too)
{"serverkey", PF_sv_serverkeystring,0,0, 0, 354, D("string(string key)", "Look up a key in the server's public serverinfo string. If the key contains binary data then it will be truncated at the first null.")},//
{"serverkeyfloat", PF_sv_serverkeyfloat,0,0, 0, 0, D("float(string key, optional float assumevalue)", "Version of serverkey that returns the value as a float (which avoids tempstrings).")},//
{"serverkeyblob", PF_sv_serverkeyblob,0,0, 0, 0, D("int(string key, optional void *ptr, int maxsize)", "Version of serverkey that returns data as a blob (ie: binary data that may contain nulls). Returns the full blob size, even if truncated (pass maxsize=0 to query required storage).")},//
@ -13401,7 +13401,7 @@ void PR_DumpPlatform_f(void)
{"SOUNDFLAG_RELIABLE", "const float", QW|NQ, D("The sound will be sent reliably, and without regard to phs."), CF_SV_RELIABLE},
{"SOUNDFLAG_ABSVOLUME", "const float", CS, D("The sample's volume is not scaled by the volume cvar. Use with caution"), CF_CL_ABSVOLUME},
{"SOUNDFLAG_FORCELOOP", "const float", QW|NQ|CS, D("The sound will restart once it reaches the end of the sample."), CF_FORCELOOP},
{"SOUNDFLAG_NOSPACIALISE", "const float", /*QW|NQ|*/CS,D("The different audio channels are played at the same volume regardless of which way the player is facing, without needing to use 0 attenuation."), CF_NOSPACIALISE},
{"SOUNDFLAG_NOSPACIALISE", "const float", QW|NQ|CS, D("The different audio channels are played at the same volume regardless of which way the player is facing, without needing to use 0 attenuation."), CF_NOSPACIALISE},
{"SOUNDFLAG_NOREVERB", "const float", QW|NQ|CS, D("Disables the use of underwater/reverb effects on this sound effect."), CF_NOREVERB},
{"SOUNDFLAG_FOLLOW", "const float", QW|NQ|CS, D("The sound's origin will updated to follow the emitting entity."), CF_FOLLOW},
{"SOUNDFLAG_NOREPLACE", "const float", QW|NQ|CS, D("Sounds started with this flag will be ignored when there's already a sound playing on that same ent-channel."), CF_NOREPLACE},