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:
parent
a88c2b6b42
commit
f7ad84adae
16
cvm/vm.c
16
cvm/vm.c
@ -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
|
||||||
|
3
cvm/vm.h
3
cvm/vm.h
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user