diff mbox

[v3] expand: Ensure result is escaped in cvtnum

Message ID 20180601102529.aq2hdwpyf546fgtf@gondor.apana.org.au (mailing list archive)
State Accepted
Delegated to: Herbert Xu
Headers show

Commit Message

Herbert Xu June 1, 2018, 10:25 a.m. UTC
On Thu, May 31, 2018 at 10:02:50PM +0200, Jilles Tjoelker wrote:
>
> This negation overflows if result is INTMAX_MIN, leading to undefined
> behaviour. Perhaps leave the memtodest call but use STADJUST to remove
> the minus sign itself, leaving only the CTLESC or nothing.

Good point.  However this turned out to be very messy so let's
just bite the bullet and make cvtnum always scan the whole string
even though it's not necessary in the other cases (the values being
always non-negative).

---8<---
The minus sign generated from arithmetic expansion is currently
unquoted which causes anomalies when the result is used in where
the quoting matters.

This patch fixes it by explicitly calling memtodest on the result
in cvtnum.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
diff mbox

Patch

diff --git a/src/expand.c b/src/expand.c
index 67350ad..14daa63 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -116,7 +116,7 @@  static char *expari(char *start, int flag);
 STATIC void expbackq(union node *, int);
 STATIC char *evalvar(char *, int);
 static size_t strtodest(const char *p, int flags);
-static void memtodest(const char *p, size_t len, int flags);
+static size_t memtodest(const char *p, size_t len, int flags);
 STATIC ssize_t varvalue(char *, int, int, int);
 STATIC void expandmeta(struct strlist *, int);
 #ifdef HAVE_GLOB
@@ -133,7 +133,7 @@  STATIC int pmatch(const char *, const char *);
 #else
 #define pmatch(a, b) !fnmatch((a), (b), 0)
 #endif
-static int cvtnum(intmax_t num, int flags);
+static size_t cvtnum(intmax_t num, int flags);
 STATIC size_t esclen(const char *, const char *);
 STATIC char *scanleft(char *, char *, char *, char *, int, int);
 STATIC char *scanright(char *, char *, char *, char *, int, int);
@@ -795,15 +795,17 @@  record:
  * Put a string on the stack.
  */
 
-static void memtodest(const char *p, size_t len, int flags)
+static size_t memtodest(const char *p, size_t len, int flags)
 {
 	const char *syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
 	char *q;
+	char *s;
 
 	if (unlikely(!len))
-		return;
+		return 0;
 
 	q = makestrspace(len * 2, expdest);
+	s = q;
 
 	do {
 		int c = (signed char)*p++;
@@ -818,6 +820,7 @@  static void memtodest(const char *p, size_t len, int flags)
 	} while (--len);
 
 	expdest = q;
+	return q - s;
 }
 
 
@@ -1711,14 +1714,13 @@  casematch(union node *pattern, char *val)
  * Our own itoa().
  */
 
-static int cvtnum(intmax_t num, int flags)
+static size_t cvtnum(intmax_t num, int flags)
 {
 	int len = max_int_length(sizeof(num));
 	char buf[len];
 
 	len = fmtstr(buf, len, "%" PRIdMAX, num);
-	memtodest(buf, len, flags);
-	return len;
+	return memtodest(buf, len, flags);
 }
 
 STATIC void