summaryrefslogtreecommitdiff
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.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;
}