[number] Add overflow checks used to be done in parse_bcd

Which were removed in 1083df8
This commit is contained in:
Ebrahim Byagowi 2019-09-07 15:27:30 +04:30 committed by GitHub
parent 47d82713a1
commit 39cf8e21be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 27 deletions

View File

@ -30,8 +30,10 @@
#include "hb.hh"
#include <float.h>
#line 35 "hb-number-parser.hh"
#line 37 "hb-number-parser.hh"
static const unsigned char _double_parser_trans_keys[] = {
0u, 0u, 43u, 57u, 46u, 57u, 48u, 57u, 43u, 57u, 48u, 57u, 48u, 101u, 48u, 57u,
46u, 101u, 0
@ -91,7 +93,7 @@ static const int double_parser_error = 0;
static const int double_parser_en_main = 1;
#line 55 "hb-number-parser.rl"
#line 70 "hb-number-parser.rl"
constexpr double _pow2 (double x) { return x * x; }
@ -130,7 +132,9 @@ strtod_rl (const char *buf, char **end_ptr)
double frac = 0;
double frac_count = 0;
unsigned int exp = 0;
bool neg = false, exp_neg = false;
bool neg = false, exp_neg = false, exp_overflow = false;
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
const unsigned int MAX_EXP = 0x7FFu; /* 1^11-1 */
p = buf;
pe = p + strlen (p);
@ -139,12 +143,12 @@ strtod_rl (const char *buf, char **end_ptr)
int cs;
#line 143 "hb-number-parser.hh"
#line 147 "hb-number-parser.hh"
{
cs = double_parser_start;
}
#line 148 "hb-number-parser.hh"
#line 152 "hb-number-parser.hh"
{
int _slen;
int _trans;
@ -170,26 +174,39 @@ _resume:
switch ( _double_parser_trans_actions[_trans] ) {
case 1:
#line 37 "hb-number-parser.rl"
#line 39 "hb-number-parser.rl"
{ neg = true; }
break;
case 4:
#line 38 "hb-number-parser.rl"
#line 40 "hb-number-parser.rl"
{ exp_neg = true; }
break;
case 2:
#line 40 "hb-number-parser.rl"
{ value = value * 10. + ((*p) - '0'); }
#line 42 "hb-number-parser.rl"
{
value = value * 10. + ((*p) - '0');
}
break;
case 3:
#line 41 "hb-number-parser.rl"
{ frac = frac * 10. + ((*p) - '0'); ++frac_count; }
#line 45 "hb-number-parser.rl"
{
if (likely (frac <= MAX_FRACT / 10))
{
frac = frac * 10. + ((*p) - '0');
++frac_count;
}
}
break;
case 5:
#line 42 "hb-number-parser.rl"
{ exp = exp * 10 + ((*p) - '0'); }
#line 52 "hb-number-parser.rl"
{
if (likely (exp * 10 + ((*p) - '0') <= MAX_EXP))
exp = exp * 10 + ((*p) - '0');
else
exp_overflow = true;
}
break;
#line 193 "hb-number-parser.hh"
#line 210 "hb-number-parser.hh"
}
_again:
@ -201,7 +218,7 @@ _again:
_out: {}
}
#line 104 "hb-number-parser.rl"
#line 121 "hb-number-parser.rl"
*end_ptr = (char *) p;
@ -209,12 +226,17 @@ _again:
if (frac_count) value += frac / _pow10 (frac_count);
if (neg) value *= -1.;
if (unlikely (exp_overflow))
{
if (value == 0) return value;
if (exp_neg) return neg ? -DBL_MIN : DBL_MIN;
else return neg ? -DBL_MAX : DBL_MAX;
}
if (exp)
{
if (exp_neg)
value /= _pow10 (exp);
else
value *= _pow10 (exp);
if (exp_neg) value /= _pow10 (exp);
else value *= _pow10 (exp);
}
return value;

View File

@ -28,6 +28,8 @@
#include "hb.hh"
#include <float.h>
%%{
machine double_parser;
@ -37,9 +39,22 @@ write data;
action see_neg { neg = true; }
action see_exp_neg { exp_neg = true; }
action add_int { value = value * 10. + (fc - '0'); }
action add_frac { frac = frac * 10. + (fc - '0'); ++frac_count; }
action add_exp { exp = exp * 10 + (fc - '0'); }
action add_int {
value = value * 10. + (fc - '0');
}
action add_frac {
if (likely (frac <= MAX_FRACT / 10))
{
frac = frac * 10. + (fc - '0');
++frac_count;
}
}
action add_exp {
if (likely (exp * 10 + (fc - '0') <= MAX_EXP))
exp = exp * 10 + (fc - '0');
else
exp_overflow = true;
}
num = [0-9]+;
@ -90,7 +105,9 @@ strtod_rl (const char *buf, char **end_ptr)
double frac = 0;
double frac_count = 0;
unsigned int exp = 0;
bool neg = false, exp_neg = false;
bool neg = false, exp_neg = false, exp_overflow = false;
const unsigned long long MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
const unsigned int MAX_EXP = 0x7FFu; /* 1^11-1 */
p = buf;
pe = p + strlen (p);
@ -108,12 +125,17 @@ strtod_rl (const char *buf, char **end_ptr)
if (frac_count) value += frac / _pow10 (frac_count);
if (neg) value *= -1.;
if (unlikely (exp_overflow))
{
if (value == 0) return value;
if (exp_neg) return neg ? -DBL_MIN : DBL_MIN;
else return neg ? -DBL_MAX : DBL_MAX;
}
if (exp)
{
if (exp_neg)
value /= _pow10 (exp);
else
value *= _pow10 (exp);
if (exp_neg) value /= _pow10 (exp);
else value *= _pow10 (exp);
}
return value;