summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2006-09-11 04:56:43 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2006-09-11 04:56:43 +0000
commitd28b0d4de83f21c85f273cbf8cba3f7b68e42ff5 (patch)
tree06a082aa5ac5539933bcd8744b5e019ed0331ce6
parent6f2530cf3a9d58707b80872e8418772e5bf0c395 (diff)
downloadcoreutils-d28b0d4de83f21c85f273cbf8cba3f7b68e42ff5.tar.xz
(eval6): Fix buffer overrun, or bad performance, if
substr's last operand is very large. Performance problem reported by Sebastian Kreft.
-rw-r--r--ChangeLog6
-rw-r--r--src/expr.c12
2 files changed, 14 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 4896c20fc..ff97f70b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2006-09-10 Paul Eggert <eggert@cs.ucla.edu>
+
+ * src/expr.c (eval6): Fix buffer overrun, or bad performance, if
+ substr's last operand is very large. Performance problem reported
+ by Sebastian Kreft.
+
2006-09-09 Jim Meyering <jim@meyering.net>
* Makefile.maint (sc_prohibit_jm_in_m4): Don't hang when there
diff --git a/src/expr.c b/src/expr.c
index e0510fc10..99bbdd8fd 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -551,21 +551,25 @@ eval6 (bool evaluate)
}
else if (nextarg ("substr"))
{
+ size_t llen;
l = eval6 (evaluate);
i1 = eval6 (evaluate);
i2 = eval6 (evaluate);
tostring (l);
+ llen = strlen (l->u.s);
if (!toarith (i1) || !toarith (i2)
- || strlen (l->u.s) < i1->u.i
+ || llen < i1->u.i
|| i1->u.i <= 0 || i2->u.i <= 0)
v = str_value ("");
else
{
+ size_t vlen = MIN (i2->u.i, llen - i1->u.i + 1);
+ char *vlim;
v = xmalloc (sizeof *v);
v->type = string;
- v->u.s = strncpy (xmalloc (i2->u.i + 1),
- l->u.s + i1->u.i - 1, i2->u.i);
- v->u.s[i2->u.i] = 0;
+ v->u.s = xmalloc (vlen + 1);
+ vlim = mempcpy (v->u.s, l->u.s + i1->u.i - 1, vlen);
+ *vlim = '\0';
}
freev (l);
freev (i1);