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