summaryrefslogtreecommitdiffstats
path: root/bin/sh/nodes.c.pat
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2009-08-23 21:09:46 +0000
committerjilles <jilles@FreeBSD.org>2009-08-23 21:09:46 +0000
commit4a8e08a1103988b9e44d3ae9584cd654796998b1 (patch)
tree907e1a91ca6ca57f1742a6081e71d2fcd1f405a4 /bin/sh/nodes.c.pat
parentf0ee7a159b9f49405e827b40fed36a844334c3ac (diff)
downloadFreeBSD-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.pat35
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);
+ }
}
OpenPOWER on IntegriCloud