From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22227 invoked by alias); 18 Apr 2017 13:54:14 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 40986 Received: (qmail 8565 invoked from network); 18 Apr 2017 13:54:14 -0000 X-Qmail-Scanner-Diagnostics: from mx1.redhat.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(209.132.183.28):SA:0(-5.0/5.0):. Processed in 0.795867 secs); 18 Apr 2017 13:54:14 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=RCVD_IN_DNSWL_HI, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: kdudka@redhat.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf1.redhat.com designates 209.132.183.28 as permitted sender) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E6F6E811A7 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=kdudka@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com E6F6E811A7 From: Kamil Dudka To: =?ISO-8859-1?Q?J=E9r=E9mie?= Roquet Cc: zsh-workers@zsh.org, Bart Schaefer Subject: Re: unbounded recursive call in a shell script crashes zsh Date: Tue, 18 Apr 2017 15:54:18 +0200 Message-ID: <3185849.ijjV0Re2JH@kdudka-nb> User-Agent: KMail/4.14.10 (Linux/4.9.16-gentoo; KDE/4.14.29; x86_64; ; ) In-Reply-To: References: <2960832.nVDpiBkaWZ@kdudka-nb> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart1556590.AFU38GxEvX" Content-Transfer-Encoding: 7Bit X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 18 Apr 2017 13:54:09 +0000 (UTC) --nextPart1556590.AFU38GxEvX Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" On Thursday, April 13, 2017 18:01:13 J=C3=A9r=C3=A9mie Roquet wrote: > 2017-04-13 17:21 GMT+02:00 J=C3=A9r=C3=A9mie Roquet : > > Hence a total of 5856 bytes per recursion, or 5719 kiB for 10000 > > recursions. > Sorry, I meant 1000 recursions, obviously. >=20 > Here are the numbers when compiling using -O3 instead of -O0 -ggdb =E2= =80=94 > probably more useful for optimization: >=20 > execlist: 400 bytes > execpline: 416 bytes > execpline2: 224 bytes > execcmd_exec: 4864 bytes > execshfunc: 336 bytes > doshfunc: 704 bytes > runshfunc: 336 bytes > execode: 80 bytes > execlist: 400 bytes > execpline: 416 bytes > execpline2: 224 bytes > execcmd_exec: 4864 bytes > execif: 80 bytes >=20 > Aggregated: >=20 > execlist: 800 bytes > execpline: 832 bytes > execpline2: 448 bytes > execcmd_exec: 9728 bytes > execshfunc: 336 bytes > doshfunc: 704 bytes > runshfunc: 336 bytes > execode: 80 bytes > execif: 80 bytes >=20 > Hence an even higher total of 13344 bytes per recursion, or 13032 kiB= > for 1000 recursions. >=20 > If I'm not mistaken, execcmd_exec seems to account for 73% of the sta= ck > usage. Thanks for the analysis! I tried to apply the attached patch on top of= my=20 previous patch but the total saving of stack allocation was only up to = 10%,=20 depending on the compiler flags. So it is not worth the troubles. Wha= t=20 helped significantly to make the default shell call nesting limit reach= able=20 again was the -fconserve-stack option of GCC. Kamil --nextPart1556590.AFU38GxEvX Content-Disposition: attachment; filename="0001-execcmd_exec-reduce-stack-allocation-in-favour-of-he.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="UTF-8"; name="0001-execcmd_exec-reduce-stack-allocation-in-favour-of-he.patch" >>From 98fb1642f4b809f4984390871b982cc37155d9ed Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Tue, 18 Apr 2017 15:03:55 +0200 Subject: [PATCH] execcmd_exec: reduce stack allocation in favour of heap --- Src/exec.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Src/exec.c b/Src/exec.c index cde549e..b28db61 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2654,9 +2654,9 @@ execcmd_exec(Estate state, Execcmd_params eparams, LinkList filelist = NULL; LinkNode node; Redir fn; - struct multio *mfds[10]; + struct multio **mfds; char *text; - int save[10]; + int *save; int fil, dfil, is_cursh, do_exec = 0, redir_err = 0, i; int nullexec = 0, magic_assign = 0, forked = 0; int is_shfunc = 0, is_builtin = 0, is_exec = 0, use_defpath = 0; @@ -2689,11 +2689,6 @@ execcmd_exec(Estate state, Execcmd_params eparams, */ use_cmdoutval = !args; - for (i = 0; i < 10; i++) { - save[i] = -2; - mfds[i] = NULL; - } - /* If the command begins with `%', then assume it is a * * reference to a job in the job table. */ if ((type == WC_SIMPLE || type == WC_TYPESET) && args && nonempty(args) && @@ -3370,6 +3365,13 @@ execcmd_exec(Estate state, Execcmd_params eparams, } } + save = zalloc(10 * sizeof(int)); + mfds = zalloc(10 * sizeof(struct multio *)); + for (i = 0; i < 10; i++) { + save[i] = -2; + mfds[i] = NULL; + } + /* Add pipeline input/output to mnodes */ if (input) addfd(forked, save, mfds, 0, input, 0, NULL); @@ -3616,6 +3618,8 @@ execcmd_exec(Estate state, Execcmd_params eparams, if (mfds[i] && mfds[i]->ct >= 2) closemn(mfds, i, REDIR_CLOSE); + zfree(mfds, 10 * sizeof(struct multio *)); + if (nullexec) { /* * If nullexec is 2, we have variables to add with the redirections @@ -4003,6 +4007,7 @@ execcmd_exec(Estate state, Execcmd_params eparams, fixfds(save); done: + zfree(save, 10 * sizeof(int)); if (isset(POSIXBUILTINS) && (cflags & (BINF_PSPECIAL|BINF_EXEC)) && !(orig_cflags & BINF_COMMAND)) { -- 2.10.2 --nextPart1556590.AFU38GxEvX--