From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2137 invoked by alias); 27 Feb 2012 16:54:07 -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: 30279 Received: (qmail 22847 invoked from network); 27 Feb 2012 16:54:06 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.6 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,NML_ADSP_CUSTOM_MED,RCVD_IN_DNSWL_LOW, T_DKIM_INVALID autolearn=no version=3.3.2 Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf.google.com designates 209.85.214.171 as permitted sender) Received-SPF: pass (google.com: domain of mikachu@gmail.com designates 10.182.1.40 as permitted sender) client-ip=10.182.1.40; Authentication-Results: mr.google.com; spf=pass (google.com: domain of mikachu@gmail.com designates 10.182.1.40 as permitted sender) smtp.mail=mikachu@gmail.com; dkim=pass header.i=mikachu@gmail.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=XB+BuDsujKgfenPTwl+nJk2CE6LNp8ea+TXsdWod0N8=; b=jAQ6efe6MDnzh+iIXenup/5OHNi5ngUhiygqjPOCjnYsKmy5UDAop2XGP5CtqcPcvn I5mFa/IzeBTQT22OX89kdcmWVJvopc9OroH9rbAHrrNiiJPqL+j9Dm1+tSTQlytt8uji te//lRTfI64ISpz2/Q2CPY0fm24LC3DyAXraA= MIME-Version: 1.0 In-Reply-To: References: <20120227162251.GA17559@zaphod.q-ix.net> Date: Mon, 27 Feb 2012 17:54:02 +0100 Message-ID: Subject: Re: Integer overflow during brace expansion From: Mikael Magnusson To: Leon Weber Cc: zsh-workers@zsh.org Content-Type: text/plain; charset=UTF-8 On 27 February 2012 17:52, Mikael Magnusson wrote: > On 27 February 2012 17:22, Leon Weber wrote: >> Hi, >> >> When parsing and expanding 'dotdot' type brace expressions (e.g. {1..3}), >> zsh can encounter integer overflows because the range start and end >> values are stored in two integers without proper bounds checking >> (rstart and rend in glob.c:2092). Particularly, >> this happens when one of the range boundaries is <=-2147483648 >> or >=2147483648, like in this example: >> >>> zsh% echo {-2147483648..-2147483646} >> >> This will cause zsh to eat up 100% CPU iterating through the loop declared >> in line 2147 in glob.c. In that loop, rend is decreased until it underflows. >> In the third and fourth iterations, we have these conditions: > [snippysnip] >> This gdb output clearly shows that rend has underflown and is now at the >> far positive end of the valid integer values. zsh will keep iterating >> over that loop and decreasing rend for a really long time. >> >> For comparison, a bash shell handles this correctly: >> >>> bash$ echo {-2147483648..-2147483646} >>> -2147483648 -2147483647 -2147483646 > > $ echo {-2147483648..2147483646} > zsh: segmentation fault bash > and if you do this > $ echo {0..214783646}^C > it doesn't free the allocated memory until you exit the shell :). > > (Of course, just for comparison. In zsh you can't even abort the > process with ctrl-c ;).) > > The fix is fairly simple, just change the types involved to zlong. A > problem is that sprintf is used to convert the generated numbers back > to a string, and zlong can be an int or a long, but I forgot if we > have a modifier macro that expands to the correct thing. I remember > asking about it before (and possibly saying I would look in to fixing > it), but at the moment I don't remember what the result was. > > With hardcoding it to %ld though, we get ie, this: diff --git i/Src/glob.c w/Src/glob.c index 8f8127c..78b197c 100644 --- i/Src/glob.c +++ w/Src/glob.c @@ -2089,7 +2089,8 @@ xpandbraces(LinkList list, LinkNode *np) char *dots, *p, *dots2 = NULL; LinkNode olast = last; /* Get the first number of the range */ - int rstart = zstrtol(str+1,&dots,10), rend = 0, err = 0, rev = 0, rincr = 1; + zlong rstart = zstrtol(str+1,&dots,10), rend = 0; + int err = 0, rev = 0, rincr = 1; int wid1 = (dots - str) - 1, wid2 = (str2 - dots) - 2, wid3 = 0; int strp = str - str3; @@ -2134,7 +2135,7 @@ xpandbraces(LinkList list, LinkNode *np) } if (rstart > rend) { /* Handle decreasing ranges correctly. */ - int rt = rend; + zlong rt = rend; rend = rstart; rstart = rt; rev = !rev; @@ -2147,7 +2148,7 @@ xpandbraces(LinkList list, LinkNode *np) for (; rend >= rstart; rend -= rincr) { /* Node added in at end, so do highest first */ p = dupstring(str3); - sprintf(p + strp, "%0*d", minw, rend); + sprintf(p + strp, "%0*ld", minw, rend); strcat(p + strp, str2 + 1); insertlinknode(list, last, p); if (rev) /* decreasing: add in reverse order. */