Closes (signed integer shift left does not correctly check overflow in the interpreter when shifting by 0 bits), Closes (integer division overflow is not handled in the interpreter and crashes it) and closes (lar instruction does not accept negative bounds in interpreter when doing array index checking).

This commit is contained in:
carl 2019-06-16 00:42:48 +08:00
parent 1ec55dfc6e
commit ef246bd8e2
3 changed files with 59 additions and 10 deletions

View file

@ -58,12 +58,13 @@ PRIVATE void arr(int type, /* operation TYPE */
{
register ptr desc = dppop(); /* array DESCriptor */
register size obj_size; /* OBJect SIZE */
register long diff = /* between index and lower bound */
spop(elm_size) - mem_lds(desc, elm_size);
long index = spop(elm_size);
long diff = /* between index and lower bound */
index - mem_lds(desc, elm_size);
register ptr arr_addr = dppop();/* ARRay ADDRess */
if (must_test && !(IgnMask&BIT(EARRAY))) {
if (diff < 0 || diff > mem_lds(desc + elm_size, elm_size)) {
if (diff < 0 || index > mem_lds(desc + elm_size, elm_size)) {
trap(EARRAY);
}
}

View file

@ -14,7 +14,7 @@
#include "text.h"
#include "fra.h"
PRIVATE long adi(long, long, size), sbi(long, long, size), dvi(long, long);
PRIVATE long adi(long, long, size), sbi(long, long, size), dvi(long, long, size);
PRIVATE long mli(long, long, size), rmi(long, long), ngi(long, size);
PRIVATE long sli(long, long, size), sri(long, long, size);
@ -55,7 +55,7 @@ void DoDVI(register size l)
LOG(("@I6 DoDVI(%ld)", l));
spoilFRA();
npush(dvi(spop(l), t), l);
npush(dvi(spop(l), t, l), l);
}
/** RMI w: Remainder (*) */
@ -162,7 +162,7 @@ PRIVATE long mli(long w1, long w2, size nbytes)
return (w1 * w2);
}
PRIVATE long dvi(long w1, long w2)
PRIVATE long dvi(long w1, long w2, size nbytes)
{
if (w2 == 0) {
if (!(IgnMask&BIT(EIDIVZ))) {
@ -170,6 +170,20 @@ PRIVATE long dvi(long w1, long w2)
}
else return (0L);
}
/* Check for division overflow. */
if ((w1 == i_mins(nbytes)) && (w2 == -1))
{
if (must_test && !(IgnMask&BIT(EIOVFL)))
{
trap(EIOVFL);
} else return i_mins(nbytes);
}
if (must_test && !(IgnMask&BIT(EIOVFL)))
{
}
return (w1 / w2);
}
@ -212,11 +226,24 @@ PRIVATE long sli(long w1, long w2, size nbytes)
if (!(IgnMask&BIT(EIOVFL))) {
/* check overflow */
if ( (w1 >= 0 && (w1 >> (nbytes*8 - w2)) != 0)
|| (w1 < 0 && (w1 >> (nbytes*8 - w2)) != -1)
) {
/* If the value is positive, then check, this is taken
* from rule INT32-C of SEI website.
*/
if ((w1 >= 0) && (w1 > (i_maxs(nbytes) >> w2)))
{
trap(EIOVFL);
}
if ((w1 < 0) && (w1 < (i_mins(nbytes) >> w2)))
{
trap(EIOVFL);
}
/* if ((w1 < 0) && (w2 != 0) && ((w1 >> (nbytes*8 - w2)) != -1))
{
trap(EIOVFL);
}*/
}
}

View file

@ -45,15 +45,36 @@ extern void disassemble(void);
extern void tally(void);
extern void out_tally(void);
/** Check dynamically that the interpreter can run on the target machine. */
static void check_requirements(char *name)
{
/* Verify that shift right supported signed shifts. According to ISO C90,
* this is not mandatory, we should not support it here!
*/
int shrv = -4;
if ((shrv >> 1) != -2)
{
fprintf(stderr,
"%s compiled with compiler that does not support signed right shifts. Aborted.",
name);
exit(1);
}
}
int main(int argc, char *argv[])
{
register int i;
register int nosetjmp = 1;
int must_disassemble = 0;
int must_tally = 0;
prog_name = argv[0];
check_requirements(prog_name);
/* Initialize the EM machine */
PreIgnMask = 0;
FRALimit = FRALIMIT;