ref: d60399e18345e69419489f201f27f19f1a5616b2
parent: 7fcae265252c0a29cf2a4b0c1474b35e7ad39619
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Dec 25 01:46:07 EST 2024
validate bytecode data - fail on invalid instructions Also produce a compile-time warning if an opcode isn't handled by the logic, to avoid boxl style problems in the future.
--- a/flisp.c
+++ b/flisp.c
@@ -1973,7 +1973,7 @@
cvalue_t *arr = (cvalue_t*)ptr(args[0]);
cv_pin(arr);
char *data = cv_data(arr);
- uint32_t ms;
+ int ms;
if((uint8_t)data[4] >= N_OPCODES){
// read syntax, shifted 48 for compact text representation
size_t i, sz = cv_len(arr);
@@ -1988,6 +1988,8 @@
}
ms = compute_maxstack((uint8_t*)data, cv_len(arr));
#endif
+ if(ms < 0)
+ lerrorf(FL(ArgError), "invalid bytecode");
PUT_INT32(data, ms);
function_t *fn = alloc_words(4);
value_t fv = tagptr(fn, TAG_FUNCTION);
--- a/gen.lsp
+++ b/gen.lsp
@@ -111,7 +111,7 @@
(lms ())
(i 0))
(begin
- (io-write c-header "enum {\n")
+ (io-write c-header "typedef enum {\n")
(for-each-n
(λ (cop lop argc f)
(begin
@@ -125,7 +125,7 @@
(set! lms (cons f lms))
(set! i (1+ i))))
opcodes 4)
- (io-write c-header "\tN_OPCODES\n};\n\n")
+ (io-write c-header "\tN_OPCODES\n}opcode_t;\n\n")
(io-write c-header "extern const Builtin builtins[N_OPCODES];\n")
(io-close c-header)
(io-write c-code "#include \"flisp.h\"\n\n")
--- a/maxstack.inc
+++ b/maxstack.inc
@@ -1,13 +1,16 @@
-static uint32_t
+static int
compute_maxstack(uint8_t *code, size_t len)
{
uint8_t *ip = code+4, *end = code+len;
- uint32_t i, n, sp = 0, maxsp = 0;
+ int i, n, sp = 0, maxsp = 0;
while(ip < end){
if((int32_t)sp > (int32_t)maxsp)
maxsp = sp;
- switch(*ip++){
+ opcode_t op = *ip++;
+ if(op >= N_OPCODES)
+ return -1;
+ switch(op){
case OP_LOADA: case OP_LOADI8: case OP_LOADV: case OP_LOADG:
ip++; // fallthrough
case OP_LOADA0: case OP_LOADA1:
@@ -142,8 +145,20 @@
SWAP_INT32(ip);
ip += 4;
break;
+
+ case OP_CAR: case OP_CDR: case OP_CADR:
+ case OP_NOT: case OP_NEG:
+ case OP_CONSP: case OP_ATOMP: case OP_SYMBOLP:
+ case OP_NULLP: case OP_BOOLEANP: case OP_NUMBERP:
+ case OP_FIXNUMP: case OP_BOUNDP: case OP_BUILTINP:
+ case OP_FUNCTIONP: case OP_VECTORP:
+ break;
+
+ case OP_EOF_OBJECT: case N_OPCODES:
+ return -1;
}
}
assert(ip == end);
+ assert(maxsp >= 0);
return maxsp+4;
}
--- a/opcodes.h
+++ b/opcodes.h
@@ -1,4 +1,4 @@
-enum {
+typedef enum {
OP_LOADA0,
OP_LOADA1,
OP_LOADV,
@@ -95,6 +95,6 @@
OP_LOADVOID,
OP_EOF_OBJECT,
N_OPCODES
-};
+}opcode_t;
extern const Builtin builtins[N_OPCODES];