shithub: riscv

Download patch

ref: 9d8f5a14662f6500c21ac4fa0afd083fc9e2467a
parent: 6b146c70c2863bf1e9d5c4a35cbd8426c5a161e7
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Feb 8 20:37:05 EST 2014

acid: fix memory corruption due to gc

we cannot call gc() in execute() because it will gc
anonyous intermediate results which happens when we
construct a list and the elements are calculated by
calling a function thru ocall() which calls execute().

also, the _thiscmd symbol; which is used to keep
a reference to a statement so it wont get garbage
collected; does not work as yyparse() is recursive
(include statements).

we add execrec() function which *only* gets called from
yyparse() when evaluating a statement. it will
keep a stack on the _thiscmd symbol handling the yyparse()
recursion.

we also only call gc() in execrec() before calling
execute(). so execute() will never gc() while evaluating
a statement which prevents the intermediate results
from getting collected.

--- a/sys/src/cmd/acid/acid.h
+++ b/sys/src/cmd/acid/acid.h
@@ -190,6 +190,7 @@
 Lsym*	enter(char*, int);
 void	error(char*, ...);
 void	execute(Node*);
+void	execrec(Node*);
 void	fatal(char*, ...);
 void	flatten(Node**, Node*);
 void	gc(void);
--- a/sys/src/cmd/acid/dbg.y
+++ b/sys/src/cmd/acid/dbg.y
@@ -50,11 +50,7 @@
 
 bigstmnt	: stmnt
 		{
-			/* make stmnt a root so it isn't collected! */
-			mkvar("_thiscmd")->proc = $1;
-			execute($1);
-			mkvar("_thiscmd")->proc = nil;
-			gc();
+			execrec($1);
 			if(interactive)
 				Bprint(bout, "acid: ");
 		}
--- a/sys/src/cmd/acid/exec.c
+++ b/sys/src/cmd/acid/exec.c
@@ -57,6 +57,32 @@
 }
 
 void
+execrec(Node *n)
+{
+	Value *v;
+	Lsym *s;
+
+	/* make node a root so it isn't collected! */
+	s = mkvar("_thiscmd");
+
+	v = gmalloc(sizeof(Value));
+	memset(v, 0, sizeof(Value));
+	v->type = TCODE;
+	v->cc = n;
+	v->pop = s->v;
+
+	s->v = v;
+	s->proc = n;
+
+	gc();
+	execute(n);
+
+	s->proc = s->v->cc;
+	s->v = v->pop;
+	free(v);
+}
+
+void
 execute(Node *n)
 {
 	Value *v;
@@ -66,7 +92,6 @@
 	Node res, xx;
 	static int stmnt;
 
-	gc();
 	if(gotint)
 		error("interrupted");
 
--- a/sys/src/cmd/acid/lex.c
+++ b/sys/src/cmd/acid/lex.c
@@ -569,11 +569,11 @@
 	s->lexval = t;
 
 	v = gmalloc(sizeof(Value));
-	s->v = v;
-
+	memset(v, 0, sizeof(Value));
 	v->fmt = 'X';
 	v->type = TINT;
-	memset(v, 0, sizeof(Value));
+
+	s->v = v;
 
 	return s;
 }