diff options
author | jilles <jilles@FreeBSD.org> | 2009-08-23 21:09:46 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2009-08-23 21:09:46 +0000 |
commit | 4a8e08a1103988b9e44d3ae9584cd654796998b1 (patch) | |
tree | 907e1a91ca6ca57f1742a6081e71d2fcd1f405a4 /bin/sh/nodes.c.pat | |
parent | f0ee7a159b9f49405e827b40fed36a844334c3ac (diff) | |
download | FreeBSD-src-4a8e08a1103988b9e44d3ae9584cd654796998b1.zip FreeBSD-src-4a8e08a1103988b9e44d3ae9584cd654796998b1.tar.gz |
sh: Fix crash when undefining or redefining a currently executing function.
Add a reference count to function definitions.
Memory may leak if multiple SIGINTs arrive in interactive mode,
this will be fixed later by changing SIGINT handling.
PR: bin/137640
Diffstat (limited to 'bin/sh/nodes.c.pat')
-rw-r--r-- | bin/sh/nodes.c.pat | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/bin/sh/nodes.c.pat b/bin/sh/nodes.c.pat index 10dab26..b6a8559 100644 --- a/bin/sh/nodes.c.pat +++ b/bin/sh/nodes.c.pat @@ -35,6 +35,7 @@ #include <sys/param.h> #include <stdlib.h> +#include <stddef.h> /* * Routine for dealing with parsed shell commands. */ @@ -65,17 +66,22 @@ STATIC char *nodesavestr(char *); * Make a copy of a parse tree. */ -union node * +struct funcdef * copyfunc(union node *n) { + struct funcdef *fn; + if (n == NULL) return NULL; - funcblocksize = 0; + funcblocksize = offsetof(struct funcdef, n); funcstringsize = 0; calcsize(n); - funcblock = ckmalloc(funcblocksize + funcstringsize); - funcstring = (char *)funcblock + funcblocksize; - return copynode(n); + fn = ckmalloc(funcblocksize + funcstringsize); + fn->refcount = 1; + funcblock = (char *)fn + offsetof(struct funcdef, n); + funcstring = (char *)fn + funcblocksize; + copynode(n); + return fn; } @@ -144,14 +150,25 @@ nodesavestr(char *s) } +void +reffunc(struct funcdef *fn) +{ + fn->refcount++; +} + /* - * Free a parse tree. + * Decrement the reference count of a function definition, freeing it + * if it falls to 0. */ void -freefunc(union node *n) +unreffunc(struct funcdef *fn) { - if (n) - ckfree(n); + if (fn) { + fn->refcount--; + if (fn->refcount > 0) + return; + ckfree(fn); + } } |