Use is_numeric_string_ex for zval_get_long etc.

This commit is contained in:
Andrea Faulds 2016-01-26 22:08:19 +00:00
parent c21f088485
commit 5ac4a0cc4b
4 changed files with 35 additions and 16 deletions

View File

@ -370,11 +370,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de
if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) { if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
return 0; return 0;
} }
if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) { *dest = zend_dval_to_lval_cap(Z_DVAL_P(arg));
*dest = (Z_DVAL_P(arg) > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
} else {
*dest = zend_dval_to_lval(Z_DVAL_P(arg));
}
} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
double d; double d;
int type; int type;
@ -384,11 +380,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de
if (UNEXPECTED(zend_isnan(d))) { if (UNEXPECTED(zend_isnan(d))) {
return 0; return 0;
} }
if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) { *dest = zend_dval_to_lval_cap(d);
*dest = (d > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN;
} else {
*dest = zend_dval_to_lval(d);
}
} else { } else {
return 0; return 0;
} }

View File

@ -325,8 +325,11 @@ try_again:
case IS_STRING: case IS_STRING:
{ {
zend_string *str = Z_STR_P(op); zend_string *str = Z_STR_P(op);
if (base == 10) {
ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base)); ZVAL_LONG(op, zval_get_long(op));
} else {
ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base));
}
zend_string_release(str); zend_string_release(str);
} }
break; break;
@ -756,10 +759,24 @@ try_again:
case IS_DOUBLE: case IS_DOUBLE:
return zend_dval_to_lval(Z_DVAL_P(op)); return zend_dval_to_lval(Z_DVAL_P(op));
case IS_STRING: case IS_STRING:
if (!silent) { {
if (is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), NULL, NULL, -1)==0) { zend_uchar type;
zend_error(E_WARNING, "A non-numeric value encountered"); zend_long lval;
double dval;
if (0 == (type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval, silent ? 1 : -1))) {
if (!silent) {
zend_error(E_WARNING, "A non-numeric value encountered");
}
return 0; return 0;
} else if (EXPECTED(type == IS_LONG)) {
return lval;
} else {
/* Previously we used strtol here, not is_numeric_string,
* and strtol gives you LONG_MAX/_MIN on overflow.
* We use use saturating conversion to emulate strtol()'s
* behaviour.
*/
return zend_dval_to_lval_cap(dval);
} }
} }
return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10); return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10);

View File

@ -122,6 +122,16 @@ static zend_always_inline zend_long zend_dval_to_lval(double d)
return (zend_long)d; return (zend_long)d;
} }
#endif #endif
static zend_always_inline zend_long zend_dval_to_lval_cap(double d)
{
if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) {
return 0;
} else if (!ZEND_DOUBLE_FITS_LONG(d)) {
return (d > 0 ? ZEND_LONG_MAX : ZEND_LONG_MIN);
}
return (zend_long)d;
}
/* }}} */ /* }}} */
#define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9')

View File

@ -154,7 +154,7 @@ PHP_FUNCTION(intval)
ZEND_PARSE_PARAMETERS_END(); ZEND_PARSE_PARAMETERS_END();
#endif #endif
if (Z_TYPE_P(num) != IS_STRING) { if (Z_TYPE_P(num) != IS_STRING || base == 10) {
RETVAL_LONG(zval_get_long(num)); RETVAL_LONG(zval_get_long(num));
} else { } else {
RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base)); RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base));