From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24971 invoked from network); 5 Jan 2009 21:55:23 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.5 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 5 Jan 2009 21:55:23 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 52266 invoked from network); 5 Jan 2009 21:55:13 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 5 Jan 2009 21:55:13 -0000 Received: (qmail 29793 invoked by alias); 5 Jan 2009 21:55:06 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 26249 Received: (qmail 29777 invoked from network); 5 Jan 2009 21:55:06 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 5 Jan 2009 21:55:06 -0000 Received: from mtaout02-winn.ispmail.ntl.com (mtaout02-winn.ispmail.ntl.com [81.103.221.48]) by bifrost.dotsrc.org (Postfix) with ESMTP id 906E2802720C for ; Mon, 5 Jan 2009 22:54:59 +0100 (CET) Received: from aamtaout03-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout02-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20090105215458.IWVF4080.mtaout02-winn.ispmail.ntl.com@aamtaout03-winn.ispmail.ntl.com>; Mon, 5 Jan 2009 21:54:58 +0000 Received: from pws-pc ([81.107.45.176]) by aamtaout03-winn.ispmail.ntl.com (InterMail vG.2.02.00.01 201-2161-120-102-20060912) with ESMTP id <20090105215458.MSET2093.aamtaout03-winn.ispmail.ntl.com@pws-pc>; Mon, 5 Jan 2009 21:54:58 +0000 Date: Mon, 5 Jan 2009 21:54:49 +0000 From: Peter Stephenson To: "Zsh Workers" Cc: 418199@bugs.debian.org Subject: Re: Segfault on really long paths Message-ID: <20090105215449.4c226f2f@pws-pc> In-Reply-To: <2d460de70812291619y5b32aadcu733cf06c9d197e1f@mail.gmail.com> References: <2d460de70812291619y5b32aadcu733cf06c9d197e1f@mail.gmail.com> X-Mailer: Claws Mail 3.6.1 (GTK+ 2.14.5; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Cloudmark-Analysis: v=1.0 c=1 a=NLZqzBF-AAAA:8 a=fHIguck8N8W420dG_vMA:9 a=8Kn9zo795CsCbliUdyQA:7 a=dOUxlneJ_PSkd35atn5O7LFb_qcA:4 a=LY0hPdMaydYA:10 a=ZfyWQJYG1gAA:10 X-Virus-Scanned: ClamAV 0.92.1/8837/Mon Jan 5 17:08:06 2009 on bifrost X-Virus-Status: Clean On Tue, 30 Dec 2008 01:19:51 +0100 "Richard Hartmann" wrote: > richih@adamantium ~ % for i in {1..1000}; do mkdir 0123456789; cd > 0123456789; done > [1] 24398 segmentation fault zsh > richih@adamantium ~ % > > It would be better to throw an error than to segfault. This is one major culprit, there may be others. If we've *really* run out of memory there are far too many cases to trap, but there was an arbitrary limit here that I really don't like. This is reasonably well optimized in the case of no metafied characters (unless I've screwed up). Index: Src/utils.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/utils.c,v retrieving revision 1.207 diff -u -r1.207 utils.c --- Src/utils.c 27 Nov 2008 17:05:42 -0000 1.207 +++ Src/utils.c 5 Jan 2009 21:50:46 -0000 @@ -3704,26 +3704,67 @@ return mlen; } -/* This function converts a zsh internal string to a form which can be * - * passed to a system call as a filename. The result is stored in a * - * single static area. NULL returned if the result is longer than * - * 4 * PATH_MAX. */ +/* + * This function converts a zsh internal string to a form which can be + * passed to a system call as a filename. The result is stored in a + * single static area, sized to fit. If there is no Meta character + * the original string is returned. + */ /**/ mod_export char * unmeta(const char *file_name) { - static char fn[4 * PATH_MAX]; + static char *fn; + static int sz; char *p; const char *t; + int newsz, meta; + + meta = 0; + for (t = file_name; *t; t++) { + if (*t == Meta) + meta = 1; + } + if (!meta) { + /* + * don't need allocation... free if it's long, see below + */ + if (sz > 4 * PATH_MAX) { + zfree(fn, sz); + fn = NULL; + sz = 0; + } + return (char *) file_name; + } + + newsz = (t - file_name) + 1; + /* + * Optimisation: don't resize if we don't have to. + * We need a new allocation if + * - nothing was allocated before + * - the new string is larger than the old one + * - the old string was larger than an arbitrary limit but the + * new string isn't so that we free up significant space by resizing. + */ + if (!fn || newsz > sz || (sz > 4 * PATH_MAX && newsz <= 4 * PATH_MAX)) + { + if (fn) + zfree(fn, sz); + sz = newsz; + fn = (char *)zalloc(sz); + if (!fn) { + sz = 0; + /* + * will quite likely crash in the caller anyway... + */ + return NULL; + } + } - for (t = file_name, p = fn; *t && p < fn + 4 * PATH_MAX - 1; p++) + for (t = file_name, p = fn; *t; p++) if ((*p = *t++) == Meta) *p = *t++ ^ 32; - if (*t) - return NULL; - if (p - fn == t - file_name) - return (char *) file_name; *p = '\0'; return fn; } -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/