Bug 7748

Summary: ash: fix a memory leak
Product: Busybox Reporter: yadi.hu
Component: OtherAssignee: unassigned
Status: RESOLVED FIXED    
Severity: major CC: busybox-cvs
Priority: P5    
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Host: Target:
Build:

Description yadi.hu 2014-12-24 02:39:36 UTC
The script which triggers the leak:

while true
  do
    while true
      do
        break;
    done</dev/null
done

someone had fixed this bug, the commit is:

http://git.busybox.net/busybox/commit/shell/ash.c?id=4ba6c5d3ba3d2c7922aff6b5c2e73b8325f1cf17

but this commit results in crash running some shell scripts, so it was reverted.


I am trying to resolve this defect,below is a patch, any comments would be appreciated!

--- shell/ash.c    2011-03-13 09:45:40.000000000 +0800
+++ shell/ash.c    2014-12-23 17:34:04.000000000 +0800
@@ -8290,6 +8290,7 @@
     void (*evalfn)(union node *, int);
     int status;
     int int_level;
+    struct stackmark smark;
 
     SAVE_INT(int_level);
 
@@ -8329,6 +8330,7 @@
         status = !exitstatus;
         goto setstatus;
     case NREDIR:
+        setstackmark(&smark);
         expredir(n->nredir.redirect);
         status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
         if (!status) {
@@ -8336,6 +8338,7 @@
             status = exitstatus;
         }
         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
+        popstackmark(&smark);
         goto setstatus;
     case NCMD:
         evalfn = evalcommand;
Comment 1 Yuki Machida 2018-11-20 08:35:10 UTC
Please merge a patch to upstream of busybox.

Following patch is applied to busybobx 1.29.3.
I confirmed that fix a memory leak.

% diff -uprN busybox-1_29_3/shell/ash.c busybox-1_29_3.mod/shell/ash.c 
--- busybox-1_29_3/shell/ash.c	2018-09-10 03:56:49.000000000 +0900
+++ busybox-1_29_3.mod/shell/ash.c	2018-11-20 17:19:54.412928831 +0900
@@ -9009,6 +9009,7 @@ evaltree(union node *n, int flags)
 	int checkexit = 0;
 	int (*evalfn)(union node *, int);
 	int status = 0;
+	struct stackmark smark;
 
 	if (n == NULL) {
 		TRACE(("evaltree(NULL) called\n"));
@@ -9029,6 +9030,7 @@ evaltree(union node *n, int flags)
 		status = !evaltree(n->nnot.com, EV_TESTED);
 		goto setstatus;
 	case NREDIR:
+		setstackmark(&smark);
 		errlinno = lineno = n->nredir.linno;
 		if (funcline)
 			lineno -= funcline - 1;
@@ -9040,6 +9042,7 @@ evaltree(union node *n, int flags)
 		}
 		if (n->nredir.redirect)
 			popredir(/*drop:*/ 0);
+		popstackmark(&smark);
 		goto setstatus;
 	case NCMD:
 		evalfn = evalcommand;
Comment 2 Denys Vlasenko 2019-02-26 09:04:22 UTC
Fixed in git:

commit f55161ad27b641f6e09c6c498fa8a2bdb1112b0a
Author: Ron Yorston <rmy@pobox.com>
Date:   Mon Feb 25 08:29:38 2019 +0000

    ash: eval: avoid leaking memory associated with redirections.