aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2011-10-22 22:08:47 +0000
committerchristos <christos@NetBSD.org>2011-10-22 22:08:47 +0000
commit6e136e80f3716a873f9001ea65abb482acc22a04 (patch)
tree6daf3fd76afd2d9e7d0c19318240395fdfd3e0c4
parent358c353b6dddd98a33c67d1e182f6810bdd45254 (diff)
downloadbsd-progress-6e136e80f3716a873f9001ea65abb482acc22a04.tar.gz
bsd-progress-6e136e80f3716a873f9001ea65abb482acc22a04.tar.zst
bsd-progress-6e136e80f3716a873f9001ea65abb482acc22a04.zip
Put a recursion limit to avoid DoS attacks (Maksymilian Arciemowicz)
While there do minor KNF, and do as the manual says: exit with EXIT_FAILURE
-rw-r--r--strsuftoll.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/strsuftoll.c b/strsuftoll.c
index 0e29a6d..80fc52f 100644
--- a/strsuftoll.c
+++ b/strsuftoll.c
@@ -1,4 +1,4 @@
-/* $NetBSD: strsuftoll.c,v 1.8 2008/04/28 20:23:00 martin Exp $ */
+/* $NetBSD: strsuftoll.c,v 1.9 2011/10/22 22:08:47 christos Exp $ */
/*-
* Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -67,7 +67,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: strsuftoll.c,v 1.8 2008/04/28 20:23:00 martin Exp $");
+__RCSID("$NetBSD: strsuftoll.c,v 1.9 2011/10/22 22:08:47 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#ifdef _LIBC
@@ -121,8 +121,8 @@ strsuftoll(const char *desc, const char *val,
result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
if (*errbuf != '\0')
- errx(1, "%s", errbuf);
- return (result);
+ errx(EXIT_FAILURE, "%s", errbuf);
+ return result;
}
/*
@@ -130,9 +130,9 @@ strsuftoll(const char *desc, const char *val,
* rather than exiting with it.
*/
/* LONGLONG */
-long long
-strsuftollx(const char *desc, const char *val,
- long long min, long long max, char *ebuf, size_t ebuflen)
+static long long
+__strsuftollx(const char *desc, const char *val,
+ long long min, long long max, char *ebuf, size_t ebuflen, size_t depth)
{
long long num, t;
char *expr;
@@ -141,12 +141,15 @@ strsuftollx(const char *desc, const char *val,
_DIAGASSERT(val != NULL);
_DIAGASSERT(ebuf != NULL);
- errno = 0;
- ebuf[0] = '\0';
+ if (depth > 16) {
+ snprintf(ebuf, ebuflen, "%s: Recursion limit exceeded", desc);
+ return 0;
+ }
while (isspace((unsigned char)*val)) /* Skip leading space */
val++;
+ errno = 0;
num = strtoll(val, &expr, 10);
if (errno == ERANGE)
goto erange; /* Overflow */
@@ -205,36 +208,42 @@ strsuftollx(const char *desc, const char *val,
case '*': /* Backward compatible */
case 'x':
t = num;
- num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen);
+ num *= __strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen,
+ depth + 1);
if (*ebuf != '\0')
- return (0);
+ return 0;
if (t > num) {
erange:
- snprintf(ebuf, ebuflen,
- "%s: %s", desc, strerror(ERANGE));
- return (0);
+ errno = ERANGE;
+ snprintf(ebuf, ebuflen, "%s: %s", desc, strerror(errno));
+ return 0;
}
break;
default:
- badnum: snprintf(ebuf, ebuflen,
- "%s `%s': illegal number", desc, val);
- return (0);
+ badnum:
+ snprintf(ebuf, ebuflen, "%s `%s': illegal number", desc, val);
+ return 0;
}
if (num < min) {
- /* LONGLONG */
+ /* LONGLONG */
snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
desc, (long long)num, (long long)min);
- return (0);
+ return 0;
}
if (num > max) {
- /* LONGLONG */
- snprintf(ebuf, ebuflen,
- "%s %lld is greater than %lld.",
+ /* LONGLONG */
+ snprintf(ebuf, ebuflen, "%s %lld is greater than %lld.",
desc, (long long)num, (long long)max);
- return (0);
+ return 0;
}
*ebuf = '\0';
- return (num);
+ return num;
}
+long long
+strsuftollx(const char *desc, const char *val,
+ long long min, long long max, char *ebuf, size_t ebuflen)
+{
+ return __strsuftollx(desc, val, min, max, ebuf, ebuflen, 0);
+}
#endif /* !HAVE_STRSUFTOLL */