From 9d8f5a14662f6500c21ac4fa0afd083fc9e2467a Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 9 Feb 2014 01:37:05 +0100 Subject: [PATCH] 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. --- sys/src/cmd/acid/acid.h | 1 + sys/src/cmd/acid/dbg.y | 6 +----- sys/src/cmd/acid/exec.c | 27 ++++++++++++++++++++++++++- sys/src/cmd/acid/lex.c | 6 +++--- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/sys/src/cmd/acid/acid.h b/sys/src/cmd/acid/acid.h index 897a0cc50..bd0d6b7cb 100644 --- a/sys/src/cmd/acid/acid.h +++ b/sys/src/cmd/acid/acid.h @@ -190,6 +190,7 @@ void dostop(int); Lsym* enter(char*, int); void error(char*, ...); void execute(Node*); +void execrec(Node*); void fatal(char*, ...); void flatten(Node**, Node*); void gc(void); diff --git a/sys/src/cmd/acid/dbg.y b/sys/src/cmd/acid/dbg.y index 0bc2a3d74..78dd6105e 100644 --- a/sys/src/cmd/acid/dbg.y +++ b/sys/src/cmd/acid/dbg.y @@ -50,11 +50,7 @@ prog : 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: "); } diff --git a/sys/src/cmd/acid/exec.c b/sys/src/cmd/acid/exec.c index 3d9bd590b..09663a15a 100644 --- a/sys/src/cmd/acid/exec.c +++ b/sys/src/cmd/acid/exec.c @@ -56,6 +56,32 @@ unwind(void) } } +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) { @@ -66,7 +92,6 @@ execute(Node *n) Node res, xx; static int stmnt; - gc(); if(gotint) error("interrupted"); diff --git a/sys/src/cmd/acid/lex.c b/sys/src/cmd/acid/lex.c index 0092978fa..5c7ed6c81 100644 --- a/sys/src/cmd/acid/lex.c +++ b/sys/src/cmd/acid/lex.c @@ -569,11 +569,11 @@ enter(char *name, int t) 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; }