Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: zformat: fix some misparse and overrun issues
Not closing a %( would simply read garbage memory
% zformat -f result 'before%(a-after' 'a:hello' ; echo $result
beforeaftera:hello
% zformat -f result 'before%(a-after' 'a:hello' ; echo $result
beforeafter#
It was possible to overwrite the %% and %) sequences with arbitrary
text, and %% was also undocumented. Hopefully nobody relied on this
spacekey heater.
---
Doc/Zsh/mod_zutil.yo | 2 +-
Src/Modules/zutil.c | 12 ++++++++----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/Doc/Zsh/mod_zutil.yo b/Doc/Zsh/mod_zutil.yo
index 62f87fc286..c33e3c7216 100644
--- a/Doc/Zsh/mod_zutil.yo
+++ b/Doc/Zsh/mod_zutil.yo
@@ -178,7 +178,7 @@ can be achieved by giving a negative minimum field width. If a maximum
field width is specified, the var(string) will be truncated after that
many characters. After all `tt(%)' sequences for the given var(spec)s
have been processed, the resulting string is stored in the parameter
-var(param).
+var(param). The sequence `tt(%%)' can be used to produce a literal tt(%).
The tt(%)-escapes also understand ternary expressions in the form used by
prompts. The tt(%) is followed by a `tt(LPAR())' and then an ordinary
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 28c6e8accd..e50f68ece6 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -880,10 +880,10 @@ static char *zformat_substring(char* instr, char **specs, char **outp,
* vice versa... unless we are already skipping.
*/
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
- olenp, endcharl, presence, skip || actval)))
+ olenp, endcharl, presence, skip || actval)) || !*s)
return NULL;
if (!(s = zformat_substring(s+1, specs, outp, ousedp,
- olenp, ')', presence, skip || !actval)))
+ olenp, ')', presence, skip || !actval)) || !*s)
return NULL;
} else if (skip) {
continue;
@@ -978,6 +978,7 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
/* Parse the specs in argv. */
for (ap = args + 2; *ap; ap++) {
if (!ap[0][0] || ap[0][0] == '-' || ap[0][0] == '.' ||
+ ap[0][0] == '%' || ap[0][0] == ')' ||
idigit(ap[0][0]) || ap[0][1] != ':') {
zwarnnam(nam, "invalid argument: %s", *ap);
return 1;
@@ -986,8 +987,11 @@ bin_zformat(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
}
out = (char *) zhalloc(olen = 128);
- zformat_substring(args[1], specs, &out, &oused, &olen, '\0',
- presence, 0);
+ if (!zformat_substring(args[1], specs, &out, &oused, &olen, '\0',
+ presence, 0)) {
+ zwarnnam(nam, "malformed format string");
+ return 1;
+ }
out[oused] = '\0';
setsparam(args[0], ztrdup(out));
--
2.38.1
Messages sorted by:
Reverse Date,
Date,
Thread,
Author