diff options
author | Colin Watson <cjwatson@debian.org> | 2017-03-29 01:35:00 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2017-03-29 01:35:00 +0100 |
commit | 6fabaf6fd9b07cc8bc6a17c9c4a5b76849cfc874 (patch) | |
tree | b4377d09196e24e2c6f2c2128f66f92cf7891105 /openbsd-compat/fmt_scaled.c | |
parent | 971a7653746a6972b907dfe0ce139c06e4a6f482 (diff) | |
parent | d38f05dbdd291212bc95ea80648b72b7177e9f4e (diff) |
Import openssh_7.5p1.orig.tar.gz
Diffstat (limited to 'openbsd-compat/fmt_scaled.c')
-rw-r--r-- | openbsd-compat/fmt_scaled.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/openbsd-compat/fmt_scaled.c b/openbsd-compat/fmt_scaled.c index edd682a49..e5533b2de 100644 --- a/openbsd-compat/fmt_scaled.c +++ b/openbsd-compat/fmt_scaled.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */ | 1 | /* $OpenBSD: fmt_scaled.c,v 1.13 2017/03/11 23:37:23 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. | 4 | * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. |
@@ -69,7 +69,7 @@ static long long scale_factors[] = { | |||
69 | 69 | ||
70 | #define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ | 70 | #define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ |
71 | 71 | ||
72 | /** Convert the given input string "scaled" into numeric in "result". | 72 | /* Convert the given input string "scaled" into numeric in "result". |
73 | * Return 0 on success, -1 and errno set on error. | 73 | * Return 0 on success, -1 and errno set on error. |
74 | */ | 74 | */ |
75 | int | 75 | int |
@@ -81,7 +81,7 @@ scan_scaled(char *scaled, long long *result) | |||
81 | long long scale_fact = 1, whole = 0, fpart = 0; | 81 | long long scale_fact = 1, whole = 0, fpart = 0; |
82 | 82 | ||
83 | /* Skip leading whitespace */ | 83 | /* Skip leading whitespace */ |
84 | while (isascii(*p) && isspace(*p)) | 84 | while (isascii((unsigned char)*p) && isspace((unsigned char)*p)) |
85 | ++p; | 85 | ++p; |
86 | 86 | ||
87 | /* Then at most one leading + or - */ | 87 | /* Then at most one leading + or - */ |
@@ -108,7 +108,8 @@ scan_scaled(char *scaled, long long *result) | |||
108 | * (but note that E for Exa might look like e to some!). | 108 | * (but note that E for Exa might look like e to some!). |
109 | * Advance 'p' to end, to get scale factor. | 109 | * Advance 'p' to end, to get scale factor. |
110 | */ | 110 | */ |
111 | for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) { | 111 | for (; isascii((unsigned char)*p) && |
112 | (isdigit((unsigned char)*p) || *p=='.'); ++p) { | ||
112 | if (*p == '.') { | 113 | if (*p == '.') { |
113 | if (fract_digits > 0) { /* oops, more than one '.' */ | 114 | if (fract_digits > 0) { /* oops, more than one '.' */ |
114 | errno = EINVAL; | 115 | errno = EINVAL; |
@@ -124,6 +125,10 @@ scan_scaled(char *scaled, long long *result) | |||
124 | /* ignore extra fractional digits */ | 125 | /* ignore extra fractional digits */ |
125 | continue; | 126 | continue; |
126 | fract_digits++; /* for later scaling */ | 127 | fract_digits++; /* for later scaling */ |
128 | if (fpart >= LLONG_MAX / 10) { | ||
129 | errno = ERANGE; | ||
130 | return -1; | ||
131 | } | ||
127 | fpart *= 10; | 132 | fpart *= 10; |
128 | fpart += i; | 133 | fpart += i; |
129 | } else { /* normal digit */ | 134 | } else { /* normal digit */ |
@@ -131,6 +136,10 @@ scan_scaled(char *scaled, long long *result) | |||
131 | errno = ERANGE; | 136 | errno = ERANGE; |
132 | return -1; | 137 | return -1; |
133 | } | 138 | } |
139 | if (whole >= LLONG_MAX / 10) { | ||
140 | errno = ERANGE; | ||
141 | return -1; | ||
142 | } | ||
134 | whole *= 10; | 143 | whole *= 10; |
135 | whole += i; | 144 | whole += i; |
136 | } | 145 | } |
@@ -150,17 +159,22 @@ scan_scaled(char *scaled, long long *result) | |||
150 | /* Validate scale factor, and scale whole and fraction by it. */ | 159 | /* Validate scale factor, and scale whole and fraction by it. */ |
151 | for (i = 0; i < SCALE_LENGTH; i++) { | 160 | for (i = 0; i < SCALE_LENGTH; i++) { |
152 | 161 | ||
153 | /** Are we there yet? */ | 162 | /* Are we there yet? */ |
154 | if (*p == scale_chars[i] || | 163 | if (*p == scale_chars[i] || |
155 | *p == tolower(scale_chars[i])) { | 164 | *p == tolower((unsigned char)scale_chars[i])) { |
156 | 165 | ||
157 | /* If it ends with alphanumerics after the scale char, bad. */ | 166 | /* If it ends with alphanumerics after the scale char, bad. */ |
158 | if (isalnum(*(p+1))) { | 167 | if (isalnum((unsigned char)*(p+1))) { |
159 | errno = EINVAL; | 168 | errno = EINVAL; |
160 | return -1; | 169 | return -1; |
161 | } | 170 | } |
162 | scale_fact = scale_factors[i]; | 171 | scale_fact = scale_factors[i]; |
163 | 172 | ||
173 | if (whole >= LLONG_MAX / scale_fact) { | ||
174 | errno = ERANGE; | ||
175 | return -1; | ||
176 | } | ||
177 | |||
164 | /* scale whole part */ | 178 | /* scale whole part */ |
165 | whole *= scale_fact; | 179 | whole *= scale_fact; |
166 | 180 | ||
@@ -181,7 +195,9 @@ scan_scaled(char *scaled, long long *result) | |||
181 | return 0; | 195 | return 0; |
182 | } | 196 | } |
183 | } | 197 | } |
184 | errno = ERANGE; | 198 | |
199 | /* Invalid unit or character */ | ||
200 | errno = EINVAL; | ||
185 | return -1; | 201 | return -1; |
186 | } | 202 | } |
187 | 203 | ||
@@ -196,7 +212,7 @@ fmt_scaled(long long number, char *result) | |||
196 | unsigned int i; | 212 | unsigned int i; |
197 | unit_type unit = NONE; | 213 | unit_type unit = NONE; |
198 | 214 | ||
199 | abval = (number < 0LL) ? -number : number; /* no long long_abs yet */ | 215 | abval = llabs(number); |
200 | 216 | ||
201 | /* Not every negative long long has a positive representation. | 217 | /* Not every negative long long has a positive representation. |
202 | * Also check for numbers that are just too darned big to format | 218 | * Also check for numbers that are just too darned big to format |