Przeglądaj źródła

vmCompile() checks that all PC destinations are in range. STRING and CLASS opcodes read the argument length from their string, ignoring the explicit length given in the program.

master
Ian Piumarta 11 miesięcy temu
rodzic
commit
ea38861c4d
1 zmienionych plików z 11 dodań i 11 usunięć
  1. +11
    -11
      minproto.leg

+ 11
- 11
minproto.leg Wyświetl plik

@ -1,6 +1,6 @@
# minproto.leg -- minimal prototype langauge for semantic experiments # minproto.leg -- minimal prototype langauge for semantic experiments
# #
# last edited: 2024-06-20 02:30:46 by piumarta on m1mbp
# last edited: 2024-06-20 03:14:11 by piumarta on m1mbp
%{ %{
; ;
@ -4852,7 +4852,8 @@ vmInsn *vmCompile(oop grammar, oop symbol)
oop *prog = _get(program, Object,indexed); oop *prog = _get(program, Object,indexed);
int plen = _get(program, Object,isize); int plen = _get(program, Object,isize);
if (plen % 5 != 0) valueError("__match__", "program length is not a multiple of five", program); if (plen % 5 != 0) valueError("__match__", "program length is not a multiple of five", program);
vmInsn *code = calloc(plen / 5, sizeof(*code));
int clen = plen / 5;
vmInsn *code = calloc(clen, sizeof(*code));
vmCachePut(grammar, symbol, code); vmCachePut(grammar, symbol, code);
oop env = nil; oop env = nil;
int ppc = 0; int ppc = 0;
@ -4863,11 +4864,14 @@ vmInsn *vmCompile(oop grammar, oop symbol)
int arglen = integerValue(prog[ppc++], "__match__"); int arglen = integerValue(prog[ppc++], "__match__");
int ok = integerValue(prog[ppc++], "__match__"); int ok = integerValue(prog[ppc++], "__match__");
int ko = integerValue(prog[ppc++], "__match__"); int ko = integerValue(prog[ppc++], "__match__");
if (ok < 0 || ok >= clen) valueError("__match__", "OK destination out of range", program);
if (ko < 0 || ko >= clen) valueError("__match__", "KO destination out of range", program);
code[cpc] = (vmInsn){ .arg.obj = arg, .op = op, .arglen = arglen, .ok = ok, .ko = ko }; code[cpc] = (vmInsn){ .arg.obj = arg, .op = op, .arglen = arglen, .ok = ok, .ko = ko };
switch (op) { switch (op) {
case CLASS: case CLASS:
case STRING: { case STRING: {
code[cpc].arg.str = stringValue(code[cpc].arg.obj, "__match__");
code[cpc].arglen = stringLength(code[cpc].arg.obj, "__match__");
code[cpc].arg.str = stringValue (code[cpc].arg.obj, "__match__");
break; break;
} }
case RULE: { case RULE: {
@ -4875,15 +4879,15 @@ vmInsn *vmCompile(oop grammar, oop symbol)
break; break;
} }
case CALL: { case CALL: {
valueError("__match__", "program contains CALL opcode", program);
valueError("__match__", "program contains explicit CALL opcode", program);
break; break;
} }
case ACTION: { case ACTION: {
if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "ACTION argument is not a function", program);
if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "ACTION argument must be a closure", program);
break; break;
} }
case SET: { case SET: {
if (!is(Symbol, code[cpc].arg.obj)) valueError("__match__", "SET argument is not a symbol", program);
if (!is(Symbol, code[cpc].arg.obj)) valueError("__match__", "SET argument must be a symbol", program);
if (nil == env) env = new(pObject); if (nil == env) env = new(pObject);
Object_put(env, code[cpc].arg.obj, nil); Object_put(env, code[cpc].arg.obj, nil);
break; break;
@ -4894,10 +4898,6 @@ vmInsn *vmCompile(oop grammar, oop symbol)
} }
++cpc; ++cpc;
} }
#if 0
if (!cpc || code[0].op != ENTER) valueError("__match__", "program does not begin with ENTER", program);
code[0].arg.obj = env; // clone this to make a list of local variables for the rule
#endif
if (opt_d) { if (opt_d) {
printf("---- BEGIN "); println(symbol, 0); printf("---- BEGIN "); println(symbol, 0);
@ -5098,7 +5098,7 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length)
continue; continue;
} }
default: { default: {
fatal("this cannot happen");
fatal("this cannot happen %d", i->op);
break; break;
} }
} }

Ładowanie…
Anuluj
Zapisz