[openssh-commits] [openssh] 01/05: sync fmt_scaled.c with OpenBSD

git+noreply at mindrot.org git+noreply at mindrot.org
Sun Mar 12 10:51:05 AEDT 2017


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit d94c1dfef2ea30ca67b1204ada7c3b537c54f4d0
Author: Damien Miller <djm at mindrot.org>
Date:   Sun Mar 12 10:48:14 2017 +1100

    sync fmt_scaled.c with OpenBSD
    
    revision 1.13
    date: 2017/03/11 23:37:23;  author: djm;  state: Exp;  lines: +14 -1;  commitid: jnFKyHkB3CEiEZ2R;
    fix signed integer overflow in scan_scaled. Found by Nicolas Iooss
    using AFL against ssh_config. ok deraadt@ millert@
    ----------------------------
    revision 1.12
    date: 2013/11/29 19:00:51;  author: deraadt;  state: Exp;  lines: +6 -5;
    fairly simple unsigned char casts for ctype
    ok krw
    ----------------------------
    revision 1.11
    date: 2012/11/12 14:07:20;  author: halex;  state: Exp;  lines: +4 -2;
    make scan_scaled set errno to EINVAL rather than ERANGE if it encounters
    an invalid multiplier, like the man page says it should
    
    "looks sensible" deraadt@, ok ian@
    ----------------------------
    revision 1.10
    date: 2009/06/20 15:00:04;  author: martynas;  state: Exp;  lines: +4 -4;
    use llabs instead of the home-grown version;  and some comment changes
    ok ian@, millert@
    ----------------------------
---
 openbsd-compat/fmt_scaled.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/openbsd-compat/fmt_scaled.c b/openbsd-compat/fmt_scaled.c
index edd682a..e5533b2 100644
--- a/openbsd-compat/fmt_scaled.c
+++ b/openbsd-compat/fmt_scaled.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $	*/
+/*	$OpenBSD: fmt_scaled.c,v 1.13 2017/03/11 23:37:23 djm Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003 Ian F. Darwin.  All rights reserved.
@@ -69,7 +69,7 @@ static long long scale_factors[] = {
 
 #define MAX_DIGITS (SCALE_LENGTH * 3)	/* XXX strlen(sprintf("%lld", -1)? */
 
-/** Convert the given input string "scaled" into numeric in "result".
+/* Convert the given input string "scaled" into numeric in "result".
  * Return 0 on success, -1 and errno set on error.
  */
 int
@@ -81,7 +81,7 @@ scan_scaled(char *scaled, long long *result)
 	long long scale_fact = 1, whole = 0, fpart = 0;
 
 	/* Skip leading whitespace */
-	while (isascii(*p) && isspace(*p))
+	while (isascii((unsigned char)*p) && isspace((unsigned char)*p))
 		++p;
 
 	/* Then at most one leading + or - */
@@ -108,7 +108,8 @@ scan_scaled(char *scaled, long long *result)
 	 * (but note that E for Exa might look like e to some!).
 	 * Advance 'p' to end, to get scale factor.
 	 */
-	for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) {
+	for (; isascii((unsigned char)*p) &&
+	    (isdigit((unsigned char)*p) || *p=='.'); ++p) {
 		if (*p == '.') {
 			if (fract_digits > 0) {	/* oops, more than one '.' */
 				errno = EINVAL;
@@ -124,6 +125,10 @@ scan_scaled(char *scaled, long long *result)
 				/* ignore extra fractional digits */
 				continue;
 			fract_digits++;		/* for later scaling */
+			if (fpart >= LLONG_MAX / 10) {
+				errno = ERANGE;
+				return -1;
+			}
 			fpart *= 10;
 			fpart += i;
 		} else {				/* normal digit */
@@ -131,6 +136,10 @@ scan_scaled(char *scaled, long long *result)
 				errno = ERANGE;
 				return -1;
 			}
+			if (whole >= LLONG_MAX / 10) {
+				errno = ERANGE;
+				return -1;
+			}
 			whole *= 10;
 			whole += i;
 		}
@@ -150,17 +159,22 @@ scan_scaled(char *scaled, long long *result)
 	/* Validate scale factor, and scale whole and fraction by it. */
 	for (i = 0; i < SCALE_LENGTH; i++) {
 
-		/** Are we there yet? */
+		/* Are we there yet? */
 		if (*p == scale_chars[i] ||
-			*p == tolower(scale_chars[i])) {
+			*p == tolower((unsigned char)scale_chars[i])) {
 
 			/* If it ends with alphanumerics after the scale char, bad. */
-			if (isalnum(*(p+1))) {
+			if (isalnum((unsigned char)*(p+1))) {
 				errno = EINVAL;
 				return -1;
 			}
 			scale_fact = scale_factors[i];
 
+			if (whole >= LLONG_MAX / scale_fact) {
+				errno = ERANGE;
+				return -1;
+			}
+
 			/* scale whole part */
 			whole *= scale_fact;
 
@@ -181,7 +195,9 @@ scan_scaled(char *scaled, long long *result)
 			return 0;
 		}
 	}
-	errno = ERANGE;
+
+	/* Invalid unit or character */
+	errno = EINVAL;
 	return -1;
 }
 
@@ -196,7 +212,7 @@ fmt_scaled(long long number, char *result)
 	unsigned int i;
 	unit_type unit = NONE;
 
-	abval = (number < 0LL) ? -number : number;	/* no long long_abs yet */
+	abval = llabs(number);
 
 	/* Not every negative long long has a positive representation.
 	 * Also check for numbers that are just too darned big to format

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list