[PATCH] ash: preserve characters on heap in backquote parsing

Ron Yorston rmy at pobox.com
Sun Nov 11 10:33:52 UTC 2018


This bug:

   https://bugs.busybox.net/show_bug.cgi?id=9246

demonstrates a test case where BusyBox ash segfaults due to a stack
overflow.

Instead of using alloca() to preserve characters keep them on the
shell's heap-based stack.  With this change the test case returns:

    $ busybox sh test_case
    test_case: line 3141: syntax error: unterminated quoted string

That is, the test runs to completion.  If the heap is reduced to 8MB:

    $ ulimit -S -d 8192
    $ busybox sh test_case
    sh: out of memory

Heap exhaustion is detected and the shell continues to run.

function                                             old     new   delta
readtoken1                                          3265    3203     -62
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-62)             Total: -62 bytes

Signed-off-by: Ron Yorston <rmy at pobox.com>
---
 shell/ash.c | 14 ++------------
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 90eaf6faf..5ee36db93 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -12599,18 +12599,8 @@ parsebackq: {
 
 	str = NULL;
 	savelen = out - (char *)stackblock();
-	if (savelen > 0) {
-		/*
-		 * FIXME: this can allocate very large block on stack and SEGV.
-		 * Example:
-		 * echo "..<100kbytes>..`true` $(true) `true` ..."
-		 * allocates 100kb for every command subst. With about
-		 * a hundred command substitutions stack overflows.
-		 * With larger prepended string, SEGV happens sooner.
-		 */
-		str = alloca(savelen);
-		memcpy(str, stackblock(), savelen);
-	}
+	if (savelen > 0)
+		str = grabstackstr(out);
 
 	if (oldstyle) {
 		/* We must read until the closing backquote, giving special
-- 
2.19.1



More information about the busybox mailing list