cvm: guard against segfaults

I've noticed that under certain conditions, such as a stack overflow,
I would segfault, something I though was impossible because my memory
size is 0x10000 and all my integer variables are uint16_t.

After having re-read my C handbook, it seems I wasn't sufficiently
knowledgeable about type conversion rules.
This commit is contained in:
Virgil Dupras 2020-11-08 20:20:01 -05:00
parent a88c2b6b42
commit f7ad84adae
2 changed files with 12 additions and 7 deletions

View File

@ -67,10 +67,10 @@ static void iowr_blk(byte val)
} }
// get/set word from/to memory // get/set word from/to memory
static word gw(word addr) { return vm.mem[addr+1] << 8 | vm.mem[addr]; } static word gw(word addr) { return vm.mem[addr+(word)1] << 8 | vm.mem[addr]; }
static void sw(word addr, word val) { static void sw(word addr, word val) {
vm.mem[addr] = val; vm.mem[addr] = val;
vm.mem[addr+1] = val >> 8; vm.mem[addr+(word)1] = val >> 8;
} }
// pop word from SP // pop word from SP
static word pop() { static word pop() {
@ -111,7 +111,7 @@ static void execute(word wordref) {
byte wtype = vm.mem[wordref]; byte wtype = vm.mem[wordref];
switch (wtype) { switch (wtype) {
case 0: // native case 0: // native
vm.nativew[vm.mem[wordref+1]](); vm.nativew[vm.mem[wordref+(word)1]]();
break; break;
case 1: // compiled case 1: // compiled
@ -141,9 +141,13 @@ static void execute(word wordref) {
static word find(word daddr, word waddr) { static word find(word daddr, word waddr) {
byte len = vm.mem[waddr]; byte len = vm.mem[waddr];
waddr++;
while (1) { while (1) {
if ((vm.mem[daddr-1] & 0x7f) == len) { if ((vm.mem[daddr-(word)1] & 0x7f) == len) {
if (strncmp(&vm.mem[waddr+1], &vm.mem[daddr-3-len], len) == 0) { word d = daddr-3-len;
// Sanity check
if ((waddr+len >= MEMSIZE) || (d+len) >= MEMSIZE) return 0;
if (strncmp(&vm.mem[waddr], &vm.mem[d], len) == 0) {
return daddr; return daddr;
} }
} }
@ -209,7 +213,7 @@ static void PICK() {
} }
static void _roll_() { // "1 2 3 4 4 (roll)" --> "1 3 4 4" static void _roll_() { // "1 2 3 4 4 (roll)" --> "1 3 4 4"
word x = pop(); word x = pop();
while (x) { vm.mem[vm.SP+x+2] = vm.mem[vm.SP+x]; x--; } while (x) { vm.mem[vm.SP+x+(word)2] = vm.mem[vm.SP+x]; x--; }
} }
static void DROP2() { pop(); pop(); } static void DROP2() { pop(); pop(); }
static void DUP2() { // a b -- a b a b static void DUP2() { // a b -- a b a b

View File

@ -4,6 +4,7 @@
#define SP_ADDR 0xffff #define SP_ADDR 0xffff
#define RS_ADDR 0xff00 #define RS_ADDR 0xff00
#define SYSVARS RS_ADDR-0x80 #define SYSVARS RS_ADDR-0x80
#define MEMSIZE 0x10000
typedef uint8_t byte; typedef uint8_t byte;
typedef uint16_t word; typedef uint16_t word;
@ -15,7 +16,7 @@ typedef byte (*IORD) ();
typedef void (*IOWR) (byte data); typedef void (*IOWR) (byte data);
typedef struct { typedef struct {
byte mem[0x10000]; byte mem[MEMSIZE];
word SP; // parameter Stack Pointer word SP; // parameter Stack Pointer
word RS; // Return Stack pointer word RS; // Return Stack pointer
word IP; // Interpreter Pointer word IP; // Interpreter Pointer