about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>2021-04-06 23:05:03 +0900
committerJun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>2021-04-06 23:05:03 +0900
commit0f62e07c802e3fa58d1199f34fcf9772da70c264 (patch)
treea85aec1da2877c2c97439f5fac5b1b24692e1f94
parentccc7ff90a46d7b1bdcf61bae2dba20d68dca7654 (diff)
downloadzsh-0f62e07c802e3fa58d1199f34fcf9772da70c264.tar.gz
zsh-0f62e07c802e3fa58d1199f34fcf9772da70c264.tar.xz
zsh-0f62e07c802e3fa58d1199f34fcf9772da70c264.zip
48389: getkeystring() should not return ptr to local var
Now it returns NULL if called with GETKEY_SINGLE_CHAR and next character
is not found. Caller must check the return value.
-rw-r--r--ChangeLog5
-rw-r--r--Src/math.c7
-rw-r--r--Src/utils.c33
3 files changed, 36 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index d2b58a0f1..54d65ae61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2021-04-06  Jun-ichi Takimoto  <takimoto-j@kba.biglobe.ne.jp>
+
+	* 48389: Src/math.c, Src/utils.c: getkeystring(GETKEY_SINGLE_CHAR)
+	should not return a pointer to a local variable
+
 2021-04-06  Oliver Kiddle  <opk@zsh.org>
 
 	* Marc Chantreux: users/26579: Completion/Unix/Command/_surfraw:
diff --git a/Src/math.c b/Src/math.c
index b57ba42d4..1d0d86639 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -840,13 +840,18 @@ zzlex(void)
 	    if (*ptr == '#') {
 		if (*++ptr == '\\' || *ptr == '#') {
 		    int v;
+		    char *optr = ptr;
 
 		    ptr++;
 		    if (!*ptr) {
 			zerr("bad math expression: character missing after ##");
 			return EOI;
 		    }
-		    ptr = getkeystring(ptr, NULL, GETKEYS_MATH, &v);
+		    if(!(ptr = getkeystring(ptr, NULL, GETKEYS_MATH, &v))) {
+			zerr("bad math expression: bad character after ##");
+			ptr = optr;
+			return EOI;
+		    }
 		    yyval.u.l = v;
 		    return NUM;
 		}
diff --git a/Src/utils.c b/Src/utils.c
index 1ac064a4e..5a9222919 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -6697,13 +6697,21 @@ ucs4toutf8(char *dest, unsigned int wval)
  *
  * The return value is unmetafied unless GETKEY_DOLLAR_QUOTE is
  * in use.
+ *
+ * If GETKEY_SINGLE_CHAR is set in how, a next character in the given
+ * string is parsed, and the character code for it is returned in misc.
+ * The return value of the function is a pointer to the byte in the
+ * given string from where the next parsing should start. If the next
+ * character can't be found then NULL is returned.
+ * CAUTION: Currently, GETKEY_SINGLE_CHAR can be used only via
+ *          GETKEYS_MATH. Other use of it may cause trouble.
  */
 
 /**/
 mod_export char *
 getkeystring(char *s, int *len, int how, int *misc)
 {
-    char *buf, tmp[1];
+    char *buf = NULL, tmp[1];
     char *t, *tdest = NULL, *u = NULL, *sstart = s, *tbuf = NULL;
     char svchar = '\0';
     int meta = 0, control = 0, ignoring = 0;
@@ -6729,9 +6737,11 @@ getkeystring(char *s, int *len, int how, int *misc)
     DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR)) ==
 	  (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR),
 	  "BUG: incompatible options in getkeystring");
+    DPUTS((how & GETKEY_SINGLE_CHAR) && (how != GETKEYS_MATH),
+	  "BUG: unsupported options in getkeystring");
 
     if (how & GETKEY_SINGLE_CHAR)
-	t = buf = tmp;
+	t = tmp;
     else {
 	/* Length including terminating NULL */
 	int maxlen = 1;
@@ -7165,13 +7175,20 @@ getkeystring(char *s, int *len, int how, int *misc)
      */
     DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_UPDATE_OFFSET)) ==
 	  GETKEY_DOLLAR_QUOTE, "BUG: unterminated $' substitution");
-    *t = '\0';
-    if (how & GETKEY_DOLLAR_QUOTE)
-	*tdest = '\0';
-    if (how & GETKEY_SINGLE_CHAR)
+
+    if (how & GETKEY_SINGLE_CHAR) {
+	/* couldn't find a character */
 	*misc = 0;
-    else
-	*len = ((how & GETKEY_DOLLAR_QUOTE) ? tdest : t) - buf;
+	return NULL;
+    }
+    if (how & GETKEY_DOLLAR_QUOTE) {
+	*tdest = '\0';
+	*len = tdest - buf;
+    }
+    else {
+	*t = '\0';
+	*len = t - buf;
+    }
     return buf;
 }