diff options
author | jilles <jilles@FreeBSD.org> | 2013-05-11 20:51:00 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2013-05-11 20:51:00 +0000 |
commit | e0dffd814f1f48f0b8357b4219a29a93556985bd (patch) | |
tree | be11628c178535fe7fd9957134f7f49cfd4252a5 /bin | |
parent | 960e7e9fd4f902c33ef15129c7fe48d67014ca2c (diff) | |
download | FreeBSD-src-e0dffd814f1f48f0b8357b4219a29a93556985bd.zip FreeBSD-src-e0dffd814f1f48f0b8357b4219a29a93556985bd.tar.gz |
sh: Remove linked list of stack marks.
The linked list of stack marks may cause problems if the allocation stack is
used between an exception and a higher-level popstackmark(), as it may then
touch a stack mark that is local to a function which has returned.
Also, the adjustment compares to a pointer passed to realloc(), which is
undefined behaviour.
Instead of adjusting stack marks when reallocating stack blocks, ensure that
such an adjustment is never necessary by fixing a small piece of memory in
place at a stack mark. This also simplifies the code.
To avoid the problems reported in bin/175922, it remains necessary to call
setstackmark() after popstackmark() if the stack mark remains in use.
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/memalloc.c | 20 | ||||
-rw-r--r-- | bin/sh/memalloc.h | 1 |
2 files changed, 3 insertions, 18 deletions
diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c index f33a15c..cb330d0 100644 --- a/bin/sh/memalloc.c +++ b/bin/sh/memalloc.c @@ -124,7 +124,6 @@ struct stack_block { #define SPACE(sp) ((char*)(sp) + ALIGN(sizeof(struct stack_block))) static struct stack_block *stackp; -static struct stackmark *markp; char *stacknxt; int stacknleft; char *sstrend; @@ -186,8 +185,9 @@ setstackmark(struct stackmark *mark) mark->stackp = stackp; mark->stacknxt = stacknxt; mark->stacknleft = stacknleft; - mark->marknext = markp; - markp = mark; + /* Ensure this block stays in place. */ + if (stackp != NULL && stacknxt == SPACE(stackp)) + stalloc(1); } @@ -197,7 +197,6 @@ popstackmark(struct stackmark *mark) struct stack_block *sp; INTOFF; - markp = mark->marknext; while (stackp != mark->stackp) { sp = stackp; stackp = sp->prev; @@ -229,7 +228,6 @@ growstackblock(int min) int oldlen; struct stack_block *sp; struct stack_block *oldstackp; - struct stackmark *xmark; if (min < stacknleft) min = stacknleft; @@ -254,18 +252,6 @@ growstackblock(int min) stacknxt = SPACE(sp); stacknleft = newlen - (stacknxt - (char*)sp); sstrend = stacknxt + stacknleft; - - /* - * Stack marks pointing to the start of the old block - * must be relocated to point to the new block - */ - xmark = markp; - while (xmark != NULL && xmark->stackp == oldstackp) { - xmark->stackp = stackp; - xmark->stacknxt = stacknxt; - xmark->stacknleft = stacknleft; - xmark = xmark->marknext; - } INTON; } else { newlen -= ALIGN(sizeof(struct stack_block)); diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h index 95a6594..a22fa39 100644 --- a/bin/sh/memalloc.h +++ b/bin/sh/memalloc.h @@ -39,7 +39,6 @@ struct stackmark { struct stack_block *stackp; char *stacknxt; int stacknleft; - struct stackmark *marknext; }; |