ref: 93e493f391a0635753b118e2312070fce7ad5b66
parent: 89c659d80b91170a20157119975b19492c33a1dd
author: cinap_lenrek <[email protected]>
date: Sun Nov 4 14:48:27 EST 2018
libaml: allow amlmapio() to re-enter the interpreter (can happen by pciadd() -> amleval()) - make frame base pointer variable - in rwreg(), save/restore the interpreter state and allocate a Frame* on the stack - add overflow checks for frame base pointer to xec() and amleval() - gc() scans the whole stack from FP to the *real* bottom F0
--- a/sys/src/libaml/aml.c
+++ b/sys/src/libaml/aml.c
@@ -123,14 +123,17 @@
struct Interp {
uchar *pc;
Frame *fp;
+ Frame *fb;
};
static Interp interp;
static Frame stack[32];
-#define PC interp.pc
+#define PC interp.pc
#define FP interp.fp
-#define FB stack
+#define FB interp.fb
+
+#define F0 stack
#define FT &stack[nelem(stack)]
static Heap *hp;
@@ -234,7 +237,7 @@
if(h->mark & 2)
gcmark(H2D(h));
- for(f = FP; f >= FB; f--){
+ for(f = FP; f >= F0; f--){
for(i=0; i<f->narg; i++)
gcmark(f->arg[i]);
gcmark(f->env);
@@ -485,9 +488,13 @@
static uvlong
rwreg(void *reg, int off, int len, uvlong v, int write)
{
+ Interp save;
uchar buf[8], *p;
Region *r;
+ save = interp; /* save, in case we reenter the interpreter */
+ FB = FP+1; /* allocate new base */
+
switch(TAG(reg)){
case 'b':
p = reg;
@@ -498,7 +505,7 @@
putle(p, len, v);
else
v = getle(p, len);
- return v;
+ goto Out;
case 'r':
r = reg;
@@ -547,10 +554,13 @@
(Name*)r->name, spacename[r->space],
r->off, off, len, v);
}
- return v;
+ goto Out;
}
- return ~0;
+ v = -1;
+Out:
+ interp = save; /* restore */
+ return v;
}
static uvlong
@@ -937,6 +947,8 @@
void *r;
PC = pc;
+ if(FB < F0 || FB >= FT)
+ goto Out;
FP = FB;
FP->tag = 0;
@@ -946,7 +958,7 @@
FP->start = PC;
FP->end = end;
FP->aux = end;
- FB->ref = nil;
+ FP->ref = nil;
FP->dot = dot;
FP->env = env;
FP->op = nil;
@@ -2153,6 +2165,9 @@
{
Name *n;
+ FB = F0;
+ FP = F0-1;
+
fmtinstall('V', Vfmt);
fmtinstall('N', Nfmt);
@@ -2190,7 +2205,8 @@
amlexit(void)
{
amlroot = nil;
- FP = FB-1;
+ FB = F0;
+ FP = F0-1;
gc();
}
@@ -2269,6 +2285,8 @@
return -1;
if(m->eval == nil)
return xec(m->start, m->end, forkname(m->name), e, r);
+ if(FB < F0 || FB >= FT)
+ return -1;
FP = FB;
FP->op = nil;
FP->env = e;