changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: libaml: allow amlmapio() to re-enter the interpreter (can happen by pciadd() -> amleval())

changeset 6859: f1f3e27f4831
parent 6857: 1d3c6cec5137
child 6860: 359d2873c410
child 6865: 429eff304848
author: cinap_lenrek@felloff.net
date: Sun, 04 Nov 2018 19:48:27 +0100
files: sys/src/libaml/aml.c
description: 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
     1.1--- a/sys/src/libaml/aml.c
     1.2+++ b/sys/src/libaml/aml.c
     1.3@@ -123,14 +123,17 @@ struct Frame {
     1.4 struct Interp {
     1.5 	uchar	*pc;
     1.6 	Frame	*fp;
     1.7+	Frame	*fb;
     1.8 };
     1.9 
    1.10 static Interp	interp;
    1.11 static Frame	stack[32];
    1.12 
    1.13-#define PC	interp.pc
    1.14+#define	PC	interp.pc
    1.15 #define	FP	interp.fp
    1.16-#define FB	stack
    1.17+#define	FB	interp.fb
    1.18+
    1.19+#define F0	stack
    1.20 #define FT	&stack[nelem(stack)]
    1.21 
    1.22 static Heap *hp;
    1.23@@ -234,7 +237,7 @@ gc(void)
    1.24 		if(h->mark & 2)
    1.25 			gcmark(H2D(h));
    1.26 
    1.27-	for(f = FP; f >= FB; f--){
    1.28+	for(f = FP; f >= F0; f--){
    1.29 		for(i=0; i<f->narg; i++)
    1.30 			gcmark(f->arg[i]);
    1.31 		gcmark(f->env);
    1.32@@ -485,9 +488,13 @@ putle(uchar *p, int len, uvlong v)
    1.33 static uvlong
    1.34 rwreg(void *reg, int off, int len, uvlong v, int write)
    1.35 {
    1.36+	Interp save;
    1.37 	uchar buf[8], *p;
    1.38 	Region *r;
    1.39 
    1.40+	save = interp;	/* save, in case we reenter the interpreter */
    1.41+	FB = FP+1;	/* allocate new base */
    1.42+
    1.43 	switch(TAG(reg)){
    1.44 	case 'b':
    1.45 		p = reg;
    1.46@@ -498,7 +505,7 @@ rwreg(void *reg, int off, int len, uvlon
    1.47 			putle(p, len, v);
    1.48 		else
    1.49 			v = getle(p, len);
    1.50-		return v;
    1.51+		goto Out;
    1.52 
    1.53 	case 'r':
    1.54 		r = reg;
    1.55@@ -547,10 +554,13 @@ rwreg(void *reg, int off, int len, uvlon
    1.56 					(Name*)r->name, spacename[r->space],
    1.57 					r->off, off, len, v);
    1.58 		}
    1.59-		return v;
    1.60+		goto Out;
    1.61 	}
    1.62 
    1.63-	return ~0;
    1.64+	v = -1;
    1.65+Out:
    1.66+	interp = save;	/* restore */
    1.67+	return v;
    1.68 }
    1.69 
    1.70 static uvlong
    1.71@@ -937,6 +947,8 @@ xec(uchar *pc, uchar *end, Name *dot, En
    1.72 	void *r;
    1.73 
    1.74 	PC = pc;
    1.75+	if(FB < F0 || FB >= FT)
    1.76+		goto Out;
    1.77 	FP = FB;
    1.78 
    1.79 	FP->tag = 0;
    1.80@@ -946,7 +958,7 @@ xec(uchar *pc, uchar *end, Name *dot, En
    1.81 	FP->start = PC;
    1.82 	FP->end = end;
    1.83 	FP->aux = end;
    1.84-	FB->ref = nil;
    1.85+	FP->ref = nil;
    1.86 	FP->dot = dot;
    1.87 	FP->env = env;
    1.88 	FP->op = nil;
    1.89@@ -2153,6 +2165,9 @@ amlinit(void)
    1.90 {
    1.91 	Name *n;
    1.92 
    1.93+	FB = F0;
    1.94+	FP = F0-1;
    1.95+
    1.96 	fmtinstall('V', Vfmt);
    1.97 	fmtinstall('N', Nfmt);
    1.98 
    1.99@@ -2190,7 +2205,8 @@ void
   1.100 amlexit(void)
   1.101 {
   1.102 	amlroot = nil;
   1.103-	FP = FB-1;
   1.104+	FB = F0;
   1.105+	FP = F0-1;
   1.106 	gc();
   1.107 }
   1.108 
   1.109@@ -2269,6 +2285,8 @@ amleval(void *dot, char *fmt, ...)
   1.110 			return -1;
   1.111 		if(m->eval == nil)
   1.112 			return xec(m->start, m->end, forkname(m->name), e, r);
   1.113+		if(FB < F0 || FB >= FT)
   1.114+			return -1;
   1.115 		FP = FB;
   1.116 		FP->op = nil;
   1.117 		FP->env = e;