From 6e136e80f3716a873f9001ea65abb482acc22a04 Mon Sep 17 00:00:00 2001 From: christos Date: Sat, 22 Oct 2011 22:08:47 +0000 Subject: 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 --- strsuftoll.c | 57 +++++++++++++++++++++++++++++++++------------------------ 1 file 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 #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 */ -- cgit v1.2.3-56-ge451