zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: Bug report: zsh crashes when expanding long command from history.
Date: Wed, 21 Oct 2015 15:04:55 -0700	[thread overview]
Message-ID: <CAH+w=7amJUgg1Sh72nZcHA8SighELehr5ctbizXfeuW+jXA2pw@mail.gmail.com> (raw)
In-Reply-To: <151020103005.ZM1642@torch.brasslantern.com>

On Tue, Oct 20, 2015 at 10:30 AM, Bart Schaefer
<schaefer@brasslantern.com> 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);
 }

 /**/


  reply	other threads:[~2015-10-21 22:05 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-20 10:47 Dorian Haglund
2015-10-20 17:30 ` Bart Schaefer
2015-10-21 22:04   ` Bart Schaefer [this message]
2015-10-21 22:16     ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAH+w=7amJUgg1Sh72nZcHA8SighELehr5ctbizXfeuW+jXA2pw@mail.gmail.com' \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).