[v3 PATCH] expand: Ensure result is escaped in cvtnum

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxxxxxxx>

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
-- 
Email: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe dash" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux