Fixed overflow detection in number parsing functions.

This commit is contained in:
Valentin Bartenev
2017-04-10 03:43:00 +03:00
parent e0881fd85c
commit 6e7f98d6ae

View File

@@ -18,6 +18,9 @@ nxt_int_parse(const u_char *p, size_t length)
u_char c; u_char c;
nxt_uint_t val; nxt_uint_t val;
static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
if (nxt_fast_path(length != 0)) { if (nxt_fast_path(length != 0)) {
val = 0; val = 0;
@@ -32,13 +35,13 @@ nxt_int_parse(const u_char *p, size_t length)
return -1; return -1;
} }
val = val * 10 + c; if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
if (nxt_slow_path((nxt_int_t) val < 0)) {
/* An overflow. */ /* An overflow. */
return -2; return -2;
} }
val = val * 10 + c;
length--; length--;
} while (length != 0); } while (length != 0);
@@ -61,6 +64,9 @@ nxt_size_t_parse(const u_char *p, size_t length)
u_char c; u_char c;
size_t val; size_t val;
static const size_t cutoff = NXT_SIZE_T_MAX / 10;
static const size_t cutlim = NXT_SIZE_T_MAX % 10;
if (nxt_fast_path(length != 0)) { if (nxt_fast_path(length != 0)) {
val = 0; val = 0;
@@ -75,13 +81,13 @@ nxt_size_t_parse(const u_char *p, size_t length)
return -1; return -1;
} }
val = val * 10 + c; if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
if (nxt_slow_path((ssize_t) val < 0)) {
/* An overflow. */ /* An overflow. */
return -2; return -2;
} }
val = val * 10 + c;
length--; length--;
} while (length != 0); } while (length != 0);
@@ -101,8 +107,8 @@ nxt_size_t_parse(const u_char *p, size_t length)
ssize_t ssize_t
nxt_size_parse(const u_char *p, size_t length) nxt_size_parse(const u_char *p, size_t length)
{ {
u_char c, unit; u_char unit;
size_t val, max; ssize_t val, max;
nxt_uint_t shift; nxt_uint_t shift;
if (nxt_fast_path(length != 0)) { if (nxt_fast_path(length != 0)) {
@@ -130,39 +136,22 @@ nxt_size_parse(const u_char *p, size_t length)
break; break;
default: default:
max = NXT_SIZE_T_MAX; return nxt_size_t_parse(p, length + 1);
shift = 0;
length++;
break;
} }
if (nxt_fast_path(length != 0)) { val = nxt_size_t_parse(p, length);
val = 0; if (nxt_fast_path(val >= 0)) {
do { if (nxt_slow_path(val > max)) {
c = *p++; /* An overflow. */
return -2;
}
/* Values below '0' become >= 208. */ val <<= shift;
c = c - '0';
if (nxt_slow_path(c > 9)) {
return -1;
}
val = val * 10 + c;
if (nxt_slow_path(val > max)) {
/* An overflow. */
return -2;
}
length--;
} while (length != 0);
return val << shift;
} }
return val;
} }
return -1; return -1;
@@ -180,6 +169,9 @@ nxt_off_t_parse(const u_char *p, size_t length)
u_char c; u_char c;
nxt_uoff_t val; nxt_uoff_t val;
static const nxt_uoff_t cutoff = NXT_OFF_T_MAX / 10;
static const nxt_uoff_t cutlim = NXT_OFF_T_MAX % 10;
if (nxt_fast_path(length != 0)) { if (nxt_fast_path(length != 0)) {
val = 0; val = 0;
@@ -194,13 +186,13 @@ nxt_off_t_parse(const u_char *p, size_t length)
return -1; return -1;
} }
val = val * 10 + c; if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
if (nxt_slow_path((nxt_off_t) val < 0)) {
/* An overflow. */ /* An overflow. */
return -2; return -2;
} }
val = val * 10 + c;
length--; length--;
} while (length != 0); } while (length != 0);
@@ -224,6 +216,9 @@ nxt_str_int_parse(nxt_str_t *s)
size_t length; size_t length;
nxt_uint_t val; nxt_uint_t val;
static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
length = s->length; length = s->length;
if (nxt_slow_path(length == 0)) { if (nxt_slow_path(length == 0)) {
@@ -243,13 +238,13 @@ nxt_str_int_parse(nxt_str_t *s)
break; break;
} }
val = val * 10 + c; if (nxt_slow_path(val >= cutoff && (val > cutoff || c > cutlim))) {
if (nxt_slow_path((nxt_int_t) val < 0)) {
/* An overflow. */ /* An overflow. */
return -2; return -2;
} }
val = val * 10 + c;
p++; p++;
length--; length--;
@@ -271,9 +266,13 @@ double
nxt_number_parse(const u_char **start, const u_char *end) nxt_number_parse(const u_char **start, const u_char *end)
{ {
u_char c; u_char c;
nxt_bool_t overflow;
nxt_uint_t integral, frac, power; nxt_uint_t integral, frac, power;
const u_char *p; const u_char *p;
static const nxt_uint_t cutoff = NXT_INT_T_MAX / 10;
static const nxt_uint_t cutlim = NXT_INT_T_MAX % 10;
p = *start; p = *start;
integral = 0; integral = 0;
@@ -291,13 +290,15 @@ nxt_number_parse(const u_char **start, const u_char *end)
break; break;
} }
integral = integral * 10 + c; overflow = nxt_expect(0, (integral >= cutoff
&& (integral > cutoff || c > cutlim)));
if (nxt_slow_path((nxt_int_t) integral < 0)) { if (overflow) {
/* An overflow. */
return -2; return -2;
} }
integral = integral * 10 + c;
p++; p++;
} }
@@ -329,13 +330,16 @@ dot:
break; break;
} }
frac = frac * 10 + c; overflow = nxt_expect(0, (frac >= cutoff && (frac > cutoff
power *= 10; || c > cutlim))
|| power > cutoff);
if (nxt_slow_path((nxt_int_t) frac < 0 || (nxt_int_t) power < 0)) { if (overflow) {
/* An overflow. */
return -2; return -2;
} }
frac = frac * 10 + c;
power *= 10;
} }
*start = p; *start = p;