commit 2dd2a62501c1bac35dca3cbb43d7bb28dfb3d889
parent 8fac74429fc8fe6a1f102f36faa901e720a247f8
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 10 Aug 2022 07:37:25 -0400
cvm: add memory bounds checks
Diffstat:
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/posix/vm.c b/posix/vm.c
@@ -53,11 +53,18 @@ static FILE *bootfp;
static dword lblfind = 0;
// Utilities
-static byte gb(dword addr) { return vm.mem[addr]; }
+static void vmabort() { vm.PC = MEMSZ + 1; }
+static dword memchk(dword a) {
+ if (a < MEMSZ) return a;
+ printf("Out of bounds memory access! Halting");
+ vmabort();
+ return 0;
+}
+static byte gb(dword addr) { return vm.mem[memchk(addr)]; }
static word gw(dword addr) { return gb(addr) | (gb(addr+1)<<8); }
static dword gd(dword addr) { return gw(addr) | (gw(addr+2)<<16); }
static dword gpc() { dword n = gd(vm.PC); vm.PC += 4; return n; }
-static void sb(dword addr, byte b) { vm.mem[addr] = b; }
+static void sb(dword addr, byte b) { vm.mem[memchk(addr)] = b; }
static void sw(dword addr, word w) { sb(addr, w); sb(addr+1, w>>8); }
static void sd(dword addr, dword d) { sw(addr, d); sw(addr+2, d>>16); }
static dword ppeek() { return gd(vm.PSP); }
@@ -72,7 +79,7 @@ static dword current() { return gd(CURRENT); }
static dword _find(dword dict, byte *name, byte slen) {
dword a = dict;
byte len;
- while (a) {
+ while (memchk(a)) {
len = gb(a-1) & 0x3f;
if ((len == slen) && (memcmp(name, &vm.mem[a-9-len], len)==0)) {
return a;
@@ -150,7 +157,7 @@ static void BYE() { // op: 04
}
static void BYEFAIL() { // op: 05
- vm.PC = MEMSZ + 1;
+ vmabort();
}
static void QUIT() { // op: 06
@@ -529,7 +536,9 @@ static void MOVE() { // op: 4c
dword u = ppop();
dword dst = ppop();
dword src = ppop();
- memcpy(&vm.mem[dst], &vm.mem[src], u);
+ if (memchk(dst+u) && memchk(src+u)) {
+ memcpy(&vm.mem[dst], &vm.mem[src], u);
+ }
}
static void MOVEWR() { // op: 4d
@@ -543,7 +552,9 @@ static void MOVEWR() { // op: 4d
static void RTYPE() { // op: 4e
dword u = ppop();
dword a = ppop();
- write(STDOUT_FILENO, &vm.mem[a], u);
+ if (memchk(a+u)) {
+ write(STDOUT_FILENO, &vm.mem[a], u);
+ }
}
static void WNF() { // op: 4f
@@ -644,7 +655,9 @@ static void REQ() { // op: 54
dword u = ppop();
dword a2 = ppop();
dword a1 = ppop();
- ppush(memcmp(&vm.mem[a1], &vm.mem[a2], u) == 0);
+ if (memchk(a1+u) && memchk(a2+u)) {
+ ppush(memcmp(&vm.mem[a1], &vm.mem[a2], u) == 0);
+ }
}
// ( name 'dict -- entry-or-0 )
@@ -746,6 +759,7 @@ static void FCHILD () { // op: 5d
vm.PC = gd(ABORT);
return;
}
+ if (!memchk(s+len)) return;
strcpy(path, fsids[parent]);
strcat(path, "/");
strncat(path, (char*)&vm.mem[s], len);
@@ -863,6 +877,7 @@ static char *opnames[OPCNT] = {
"_fclose", "compiling"};
static void oprun1() { // run next op
+ if (!memchk(vm.PC)) return;
byte opcode = vm.mem[vm.PC++];
if ((opcode >= OPCNT) || (!ops[opcode])) {
printf("Illegal opcode %02x at PC %08x\n", opcode, vm.PC-1);