summary refs log tree commit diff
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2015-10-21 15:13:17 -0700
committerBarton E. Schaefer <schaefer@zsh.org>2015-10-21 15:13:17 -0700
commit5cb75f0d4114f83a7cf072ff8201445ae721f8c6 (patch)
tree84ef3130f82b4f53e3d0f774940aeb0c45a238b6
parentb947789d7c7a9e01880512dff1f27198f4707e50 (diff)
downloadzsh-5cb75f0d4114f83a7cf072ff8201445ae721f8c6.tar.gz
zsh-5cb75f0d4114f83a7cf072ff8201445ae721f8c6.tar.xz
zsh-5cb75f0d4114f83a7cf072ff8201445ae721f8c6.zip
36909: in getargs(), sanity-check the offsets for start and end of the requested words, in case of overflow
-rw-r--r--ChangeLog3
-rw-r--r--Src/hist.c18
2 files changed, 19 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 22e4b9478..e40242eb8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2015-10-21  Barton E. Schaefer  <schaefer@zsh.org>
 
+	* 36909: Src/hist.c: in getargs(), sanity-check the offsets for
+	start and end of the requested words, in case of overflow
+
 	* 36871: Functions/Zle/bracketed-paste-magic: move initial call
 	to "zle .bracketed-paste-magic" to occur earlier in the function
 
diff --git a/Src/hist.c b/Src/hist.c
index 9c42d85c9..007366a49 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);
 }
 
 /**/