shithub: riscv

Download patch

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;