From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11371 invoked by alias); 21 Oct 2015 22:05:03 -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: 36909 Received: (qmail 19206 invoked from network); 21 Oct 2015 22:05:01 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.0 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:content-type; bh=qXJaO8Unu19sEqN6yHYI1s9YoLtYwpBQqJ+jG2f71Rs=; b=V9PlOhAWbUrN+UTcOqk3xIKKUZbz2Wkmibtb9FoPN6wTYzmREQj1kkQs0uAgNeOU4w xMcLbtY+vfj2fVjkc8NDoeBuE8DF5u3tj3Opvc4Yl983BwTguAhGNWHTo0I8Zkg0ZdGP xpftdOZ9t0ijRhWv2qLCwtv0yn+zucrCgRtGB2NgGHeAUV5ZFkyJdjtnK2JXVlaTeh4n q7eF2aw8suH1lStb//zVPt3hQbCpOb2ICwLVmhjHqveTniaj1fA4auG6zuNGIbgS44oG OI78gGTjyhy0osZk9d9DGBh75BZGtKKimWREom7C7wlVHVUHwN20ltgnfps5NBBrxOuh lgiA== X-Gm-Message-State: ALoCoQnyyEBZHzubxCocOgwjYtGgMy1AomFfpQOTavO/G/8AbBwEnRhmXT/UELt6ik7Za9faIXcw MIME-Version: 1.0 X-Received: by 10.180.198.227 with SMTP id jf3mr14001051wic.94.1445465095911; Wed, 21 Oct 2015 15:04:55 -0700 (PDT) In-Reply-To: <151020103005.ZM1642@torch.brasslantern.com> References: <56261BBA.9000805@allegrodvt.com> <151020103005.ZM1642@torch.brasslantern.com> Date: Wed, 21 Oct 2015 15:04:55 -0700 Message-ID: Subject: Re: Bug report: zsh crashes when expanding long command from history. From: Bart Schaefer To: Zsh hackers list Content-Type: text/plain; charset=UTF-8 On Tue, Oct 20, 2015 at 10:30 AM, Bart Schaefer wrote: > On Oct 20, 12:47pm, Dorian Haglund wrote: > } The command is attached (it is 41111 characters long so I won't copy > } paste it here). > > The history mechanism is using a short integer to track the position of > each word in the command line, so any command line longer than the > maximum value of a signed short is going to cause problems. The following seems to be the most straightforward way to fix the crash. If we really want to be able to handle 32k+ command lines we'll need a more invasive patch. I suppose this might still break on a single word more than 64k characters long, but it'll break by returning the substring of the command line rather than by crashing. (This diff might get garbled, I'm not using my regular email client.) diff --git a/Src/hist.c b/Src/hist.c index 9c42d85..50a2104 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -2254,7 +2254,7 @@ static char * getargs(Histent elist, int arg1, int arg2) { short *words = elist->words; - int pos1, nwords = elist->nwords; + int pos1, pos2, nwords = elist->nwords; if (arg2 < arg1 || arg1 >= nwords || arg2 >= nwords) { /* remember, argN is indexed from 0, nwords is total no. of words */ @@ -2263,8 +2263,22 @@ getargs(Histent elist, int arg1, int arg2) return NULL; } + /* optimization for accessing entire history event */ + if (arg1 == 0 && arg2 == nwords - 1) + return dupstring(elist->node.nam); + pos1 = words[2*arg1]; - return dupstrpfx(elist->node.nam + pos1, words[2*arg2+1] - pos1); + pos2 = words[2*arg2+1]; + + /* a word has to be at least one character long, so if the position + * of a word is less than its index, we've overflowed our signed + * short integer word range and the recorded position is garbage. */ + if (pos1 < 0 || pos1 < arg1 || pos2 < 0 || pos2 < arg2) { + herrflush(); + zerr("history event too long, can't index requested words"); + return NULL; + } + return dupstrpfx(elist->node.nam + pos1, pos2 - pos1); } /**/