1
0
mirror of https://github.com/danog/PHP-Parser.git synced 2024-11-26 20:04:48 +01:00

Fix parsing of integers that overflow into floats

Integers in hex/oct/bin notation that overflowed into floats were parsed incorrectly.
This commit is contained in:
nikic 2012-01-15 16:28:25 +01:00
parent faf0351bab
commit cf3117d82d
5 changed files with 60 additions and 8 deletions

View File

@ -138,12 +138,6 @@ function resolveMacros($code) {
return 'substr(' . $args[0] . ', 1)';
}
if ('parseDNumber' == $name) {
assertArgs(1, $args, $name);
return '(double) ' . $args[0];
}
if ('parseEncapsed' == $name) {
assertArgs(2, $args, $name);

View File

@ -659,7 +659,7 @@ ctor_arguments:
common_scalar:
T_LNUMBER { $$ = Scalar_LNumber[Scalar_LNumber::parse($1)]; }
| T_DNUMBER { $$ = Scalar_DNumber[parseDNumber($1)]; }
| T_DNUMBER { $$ = Scalar_DNumber[Scalar_DNumber::parse($1)]; }
| T_CONSTANT_ENCAPSED_STRING { $$ = Scalar_String::create($1, $line, $docComment); }
| T_LINE { $$ = Scalar_LineConst[]; }
| T_FILE { $$ = Scalar_FileConst[]; }

View File

@ -20,4 +20,40 @@ class PHPParser_Node_Scalar_DNumber extends PHPParser_Node_Scalar
$line, $docComment
);
}
/**
* Parses a DNUMBER token like PHP would.
*
* @param string $str A string number
*
* @return float The parsed number
*/
public static function parse($str) {
// if string contains any of .eE just cast it to float
if (false !== strpbrk($str, '.eE')) {
return (float) $str;
}
// otherwise it's an integer notation that overflowed into a float
// if it starts with 0 it's one of the special integer notations
if ('0' === $str[0]) {
// hex
if ('x' === $str[1] || 'X' === $str[1]) {
return hexdec($str);
}
// bin
if ('b' === $str[1] || 'B' === $str[1]) {
return bindec($str);
}
// oct
// substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9)
// so that only the digits before that are used
return octdec(substr($str, 0, strcspn($str, '89')));
}
// dec
return (float) $str;
}
}

View File

@ -2157,7 +2157,7 @@ class PHPParser_Parser
}
protected function yyn284($line, $docComment) {
$this->yyval = new PHPParser_Node_Scalar_DNumber((double) $this->yyastk[$this->yysp-(1-1)], $line, $docComment);
$this->yyval = new PHPParser_Node_Scalar_DNumber(PHPParser_Node_Scalar_DNumber::parse($this->yyastk[$this->yysp-(1-1)]), $line, $docComment);
}
protected function yyn285($line, $docComment) {

View File

@ -12,6 +12,13 @@ Different float syntaxes
30.20e10;
300.200e100;
1e10000;
// various integer -> float overflows
9999999999999999999;
0xFFFFFFFFFFFFFFFF;
07777777777777777777777;
0777777777777777777777787;
0b1111111111111111111111111111111111111111111111111111111111111111;
-----
array(
0: Scalar_DNumber(
@ -44,4 +51,19 @@ array(
9: Scalar_DNumber(
value: INF
)
10: Scalar_DNumber(
value: 1.0E+19
)
11: Scalar_DNumber(
value: 1.844674407371E+19
)
12: Scalar_DNumber(
value: 7.3786976294838E+19
)
13: Scalar_DNumber(
value: 7.3786976294838E+19
)
14: Scalar_DNumber(
value: 1.844674407371E+19
)
)