diff options
Diffstat (limited to 'pez.c')
| -rw-r--r-- | pez.c | 99 |
1 files changed, 76 insertions, 23 deletions
@@ -1995,7 +1995,6 @@ f_arraypush(PezContext *cx, int argc) { Array *arr; TRY(pez_checksig(cx, argc, "array#push", "array, any")); - assert(isobj_of(cx->stktop[-2], PEZ_TArray)); arr = unbox_obj(cx->stktop[-2]); TRY(arrpushn(cx, arr, peek(cx), 1)); return push(cx, box_obj(arr)); @@ -2222,8 +2221,12 @@ addlocal(Comp *cm, uint *idx, const char *name, bool mutable, bool has_k, Val k) .has_k = has_k, .mutable = mutable, }; assert(l.scope > 0); - assert(l.sref == cm->spool.len); - assert(l.kref == cm->kpool.len); + if (l.sref != cm->spool.len) { + return comperr(cm, *name, "locals name pool overflow"), NULL; + } + if (has_k && l.kref != cm->kpool.len) { + return comperr(cm, *name, "constants pool overflow"), NULL; + } TRY(vecpush(cm->cx, &cm->spool, name, strlen(name) + 1)); if (mutable) { assert(!has_k); @@ -2271,7 +2274,9 @@ addupval(Comp *cm, struct fenv *fenv, uint8_t idx, bool arg, bool local) return up->idx; } } - assert(fenv->nupval < 256 && "upval limit"); + if (fenv->nupval == 256) { + return comperr(cm, peekchr(cm), "too many upvalues"), -2; + } fenv->upvals[fenv->nupval] = up; return fenv->nupval++; } @@ -2644,19 +2649,24 @@ primaryexpr(Comp *cm) if (local) { Local: if (local->isparam) { - assert(local->index < 256); + if (local->index >= 256) { + return comperr(cm, *buf, "too many locals"), 0; + } TRY(compop(cm, Oarg) && compbyte(cm, local->index)); } else if (local->has_k) { cm->has_k = 1; cm->k = cm->kpool.at[local->kref]; } else { - assert(local->index < 256); + if (local->index >= 256) { + return comperr(cm, *buf, "too many locals"), 0; + } TRY(compop(cm, Olocal) && compbyte(cm, local->index)); } cm->lvalue = 1; cm->lvalue_const = !local->mutable; cm->lvalue_name = &cm->spool.at[local->sref]; } else if ((idx = findupval(cm, &local, &cm->fenv, buf)) != -1) { + if (idx == -2) return 0; // propagate some error assert(idx >= 0 && idx < 256); TRY(compop(cm, Oupval) && compbyte(cm, idx)); cm->lvalue = 1; @@ -2677,7 +2687,9 @@ primaryexpr(Comp *cm) // enum-like string int i = 0; while (!aissep2((c = peekchr(cm)))) { - assert(i < sizeof buf - 2); + if (i >= sizeof buf - 2) { + return comperr(cm, c, "enum-like string too long"), 0; + } buf[i++] = c; nextchr(cm); } @@ -2701,10 +2713,16 @@ primaryexpr(Comp *cm) if (c == '"') { // string int i = 0; + vec_of(char) big = {0}; + bool bigp = 0; while ((c = nextchr(cm)) != '"') { - assert(i < sizeof buf - 2); + if (i >= sizeof buf - 2) { + bigp = 1; + vecpush(cm->cx, &big, buf, i); + } if (c == EOF) { Eof: + delvec(cm->cx, &big); return comperr(cm, c, "unterminated string constant"), 0; } if (c == '\\') { @@ -2732,13 +2750,30 @@ primaryexpr(Comp *cm) break; } case EOF: goto Eof; - default: Bad: comperr(cm, c, "bad escape sequence"); return 0; + default: Bad: + delvec(cm->cx, &big); + return comperr(cm, c, "bad escape sequence"), 0; } } - buf[i++] = c; + if (bigp) { + if (!vecpush(cm->cx, &big, &c, 1)) { + delvec(cm->cx, &big); + return 0; + } + } else { + buf[i++] = c; + } } - buf[i] = 0; - TRY(box_str(cm->cx, &cm->k, buf, i)); + if (bigp) { + vecpush(cm->cx, &big, "", 1); + } else { + buf[i] = 0; + } + if (!box_str(cm->cx, &cm->k, buf, i)) { + delvec(cm->cx, &big); + return 0; + } + delvec(cm->cx, &big); cm->has_k = 1; return 1; } @@ -3210,7 +3245,9 @@ logicexpr(Comp *cm) TRY(flushconst(cm)); off = diff = *ip - br_jumpfrom; - assert(off == diff); + if (off != diff) { + return comperr(cm, peekchr(cm), "branch target too far"), 0; + } memcpy(cm->code.at + br_arg, &off, 2); resetlastops(cm); @@ -3275,13 +3312,17 @@ condexpr(Comp *cm) TRY(expectspchr(cm, ':')); off = diff = *ip - bf_jumpfrom; - assert(off == diff); + if (off != diff) { + return comperr(cm, peekchr(cm), "branch target too far"), 0; + } memcpy(&cm->code.at[bf_arg], &off, 2); TRY(condexpr(cm) && flushconst(cm)); off = diff = *ip - b_jumpfrom; - assert(off == diff); + if (off != diff) { + return comperr(cm, peekchr(cm), "branch target too far"), 0; + } memcpy(&cm->code.at[b_arg], &off, 2); resetlastops(cm); @@ -3532,11 +3573,15 @@ forstmt(Comp *cm) TRY(compop(cm, Ob)); off = diff = b_jumpto - (*ip + 2); - assert(off == diff); + if (off != diff) { + return comperr(cm, peekchr(cm), "branch target too far"), 0; + } TRY(compbytes(cm, &off, 2)); off = diff = *ip - bf_jumpfrom; - assert(off == diff); + if (off != diff) { + return comperr(cm, peekchr(cm), "branch target too far"), 0; + } memcpy(cm->code.at + bf_arg, &off, 2); } else { // FOR [@x: ini][cond][cont] body @@ -3562,6 +3607,9 @@ forstmt(Comp *cm) beginscope(cm); TRY(decl(cm, &local, /* nofold */ 1) && discard(cm)); assert(local); + if (local->index >= 256) { + return comperr(cm, cm->spool.at[local->sref], "too many locals"), 0; + } ilocal = local - cm->fenv.locals.at; TRY(expectspchr(cm, ']')); @@ -3591,7 +3639,9 @@ forstmt(Comp *cm) assert(!cm->has_k); ncont = *ip - cont; assert(ncont > 0 && "?"); - assert(ncont < 256 && "cont too big"); + if (ncont > 256) { + return comperr(cm, peekchr(cm), "internal error: FOR cont expression too big"), 0; + } memcpy(tmp, cm->code.at + cont, ncont); *ip -= ncont; resetlastops(cm); @@ -3604,19 +3654,22 @@ forstmt(Comp *cm) resetlastops(cm); local = &cm->fenv.locals.at[ilocal]; TRY(compop(cm, local->isparam ? Osetarg : Osetloc)); - assert(local->index < 256); TRY(compbyte(cm, local->index)); TRY(compop(cm, Ob)); off = diff = b_jumpto - (*ip + 2); - assert(off == diff); + if (off != diff) { + return comperr(cm, peekchr(cm), "branch target too far"), 0; + } TRY(compbytes(cm, &off, 2)); off = diff = *ip - bf_jumpfrom; - assert(off == diff); + if (off != diff) { + return comperr(cm, peekchr(cm), "branch target too far"), 0; + } memcpy(cm->code.at + bf_arg, &off, 2); - endscope(cm); + TRY(endscope(cm)); } resetlastops(cm); @@ -3688,7 +3741,7 @@ block(Comp *cm, int endchr) return comperr(cm, EOF, "unexpected end of input"), 0; } nextchr(cm); - endscope(cm); + TRY(endscope(cm)); return 1; } |