qccx (etc) "integer" autodetection.

Check for usage of denormal floats and if found, either bail with a
descriptive error message or give a mild warning that things will probably
break. This avoids the possibility of things like RuneQuake getting "lucky"
and doing real harm, and certainly avoids the segfaults.
This commit is contained in:
Bill Currie 2010-01-13 06:36:54 +00:00 committed by Jeff Teunissen
parent 00e590f5f5
commit 0a203c0ab5
3 changed files with 26 additions and 1 deletions

View file

@ -1372,6 +1372,7 @@ struct progs_s {
dprograms_t *progs;
int progs_size;
unsigned short crc;
int denorm_found;
struct memzone_s *zone;
int zone_size;

View file

@ -127,6 +127,8 @@ PR_LoadProgsFile (progs_t * pr, QFile *file, int size, int edicts, int zone)
// store prog crc
pr->crc = CRC_Block ((byte*)&progs, sizeof (progs));
pr->denorm_found = 0;
// byte swap the header
for (i = 0; i < sizeof (progs) / 4; i++)
((int *) &progs)[i] = LittleLong (((int *) &progs)[i]);

View file

@ -45,6 +45,7 @@ static __attribute__ ((used)) const char rcsid[] =
#include "QF/hash.h"
#include "QF/pr_comp.h"
#include "QF/progs.h"
#include "QF/sys.h"
hashtab_t *opcode_table;
@ -1197,6 +1198,8 @@ check_branch (progs_t *pr, dstatement_t *st, opcode_t *op, short offset)
(long)(st - pr->pr_statements), op->opname);
}
#define ISDENORM(x) ((x) && !((x) & 0x7f800000))
static inline void
check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
unsigned short operand)
@ -1218,6 +1221,22 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type,
msg = "out of bounds global index";
goto error;
}
if (type == ev_float)
if (ISDENORM (G_INT (pr, operand))
&& !pr->denorm_found) {
pr->denorm_found = 1;
if (pr_boundscheck-> int_val) {
Sys_Printf ("DENORMAL floats detected, these progs might "
"not work. Good luck.\n");
return;
}
msg = "DENORMAL float detected. These progs are probably "
"using qccx arrays and integers. If just simple arrays "
"are being used, then they should work, but if "
"internal.qc is used, they most definitely will NOT. To"
"allow these progs to be used, set pr_boundscheck to 1.";
goto error;
}
break;
}
return;
@ -1255,7 +1274,10 @@ PR_Check_Opcodes (progs_t *pr)
&& pr->fields.think != -1 && pr->fields.frame != -1)
state_ok = 1;
if (!pr_boundscheck->int_val) {
//FIXME need to decide if I really want to always do static bounds checking
// the only problem is that it slows progs load a little, but it's the only
// way to check for qccx' evil
if (0 && !pr_boundscheck->int_val) {
for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements;
st++, i++) {
op = PR_Opcode (st->op);