Closes #193 (signed integer shift left does not correctly check overflow in the interpreter when shifting by 0 bits), Closes #192 (integer division overflow is not handled in the interpreter and crashes it) and closes #194 (lar instruction does not accept negative bounds in interpreter when doing array index checking).
This commit is contained in:
parent
1ec55dfc6e
commit
ef246bd8e2
|
@ -58,12 +58,13 @@ PRIVATE void arr(int type, /* operation TYPE */
|
||||||
{
|
{
|
||||||
register ptr desc = dppop(); /* array DESCriptor */
|
register ptr desc = dppop(); /* array DESCriptor */
|
||||||
register size obj_size; /* OBJect SIZE */
|
register size obj_size; /* OBJect SIZE */
|
||||||
register long diff = /* between index and lower bound */
|
long index = spop(elm_size);
|
||||||
spop(elm_size) - mem_lds(desc, elm_size);
|
long diff = /* between index and lower bound */
|
||||||
|
index - mem_lds(desc, elm_size);
|
||||||
register ptr arr_addr = dppop();/* ARRay ADDRess */
|
register ptr arr_addr = dppop();/* ARRay ADDRess */
|
||||||
|
|
||||||
if (must_test && !(IgnMask&BIT(EARRAY))) {
|
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);
|
trap(EARRAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "fra.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 mli(long, long, size), rmi(long, long), ngi(long, size);
|
||||||
PRIVATE long sli(long, long, size), sri(long, 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));
|
LOG(("@I6 DoDVI(%ld)", l));
|
||||||
spoilFRA();
|
spoilFRA();
|
||||||
npush(dvi(spop(l), t), l);
|
npush(dvi(spop(l), t, l), l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** RMI w: Remainder (*) */
|
/** RMI w: Remainder (*) */
|
||||||
|
@ -162,7 +162,7 @@ PRIVATE long mli(long w1, long w2, size nbytes)
|
||||||
return (w1 * w2);
|
return (w1 * w2);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE long dvi(long w1, long w2)
|
PRIVATE long dvi(long w1, long w2, size nbytes)
|
||||||
{
|
{
|
||||||
if (w2 == 0) {
|
if (w2 == 0) {
|
||||||
if (!(IgnMask&BIT(EIDIVZ))) {
|
if (!(IgnMask&BIT(EIDIVZ))) {
|
||||||
|
@ -170,6 +170,20 @@ PRIVATE long dvi(long w1, long w2)
|
||||||
}
|
}
|
||||||
else return (0L);
|
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);
|
return (w1 / w2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,11 +226,24 @@ PRIVATE long sli(long w1, long w2, size nbytes)
|
||||||
|
|
||||||
if (!(IgnMask&BIT(EIOVFL))) {
|
if (!(IgnMask&BIT(EIOVFL))) {
|
||||||
/* check overflow */
|
/* 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);
|
trap(EIOVFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((w1 < 0) && (w1 < (i_mins(nbytes) >> w2)))
|
||||||
|
{
|
||||||
|
trap(EIOVFL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if ((w1 < 0) && (w2 != 0) && ((w1 >> (nbytes*8 - w2)) != -1))
|
||||||
|
{
|
||||||
|
trap(EIOVFL);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,15 +45,36 @@ extern void disassemble(void);
|
||||||
extern void tally(void);
|
extern void tally(void);
|
||||||
extern void out_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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
register int nosetjmp = 1;
|
register int nosetjmp = 1;
|
||||||
int must_disassemble = 0;
|
int must_disassemble = 0;
|
||||||
int must_tally = 0;
|
int must_tally = 0;
|
||||||
|
|
||||||
|
|
||||||
prog_name = argv[0];
|
prog_name = argv[0];
|
||||||
|
|
||||||
|
check_requirements(prog_name);
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the EM machine */
|
/* Initialize the EM machine */
|
||||||
PreIgnMask = 0;
|
PreIgnMask = 0;
|
||||||
FRALimit = FRALIMIT;
|
FRALimit = FRALIMIT;
|
||||||
|
|
Loading…
Reference in a new issue