diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2017-12-25 13:18:45 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2017-12-26 12:39:06 +0100 |
commit | b2b2b437af5495dcb2016be6e45567ed826cb87e (patch) | |
tree | 7cf17c011f6b9c272eebf184fa47d5c35f455b2f /Zend/zend_operators.c | |
parent | efcbea43455ca4e27ec6fc5ce2f3a740a981247e (diff) | |
download | php-git-b2b2b437af5495dcb2016be6e45567ed826cb87e.tar.gz |
Add _IS_NUMBER as cast_object() target type
convert_scalar_to_number() will now call cast_object() with an
_IS_NUMBER argument, in which case the cast handler should return
either an integer or floating point number, whichever is more
appropriate.
Previously convert_scalar_to_number() unconditionally converted
objects to integers instead.
Fixes bug #53033.
Fixes bug #54973.
Fixes bug #73108.
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r-- | Zend/zend_operators.c | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 1b155f88f7..daed16e358 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -136,6 +136,26 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* { } /* }}} */ +/* {{{ convert_object_to_type: dst will be either ctype or UNDEF */ +#define convert_object_to_type(op, dst, ctype, conv_func) \ + ZVAL_UNDEF(dst); \ + if (Z_OBJ_HT_P(op)->cast_object) { \ + if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) { \ + zend_error(E_RECOVERABLE_ERROR, \ + "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\ + zend_get_type_by_const(ctype)); \ + } \ + } else if (Z_OBJ_HT_P(op)->get) { \ + zval *newop = Z_OBJ_HT_P(op)->get(op, dst); \ + if (Z_TYPE_P(newop) != IS_OBJECT) { \ + /* for safety - avoid loop */ \ + ZVAL_COPY_VALUE(dst, newop); \ + conv_func(dst); \ + } \ + } + +/* }}} */ + void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent) /* {{{ */ { try_again: @@ -172,7 +192,18 @@ try_again: } break; case IS_OBJECT: - convert_to_long_base(op, 10); + { + zval dst; + + convert_object_to_type(op, &dst, _IS_NUMBER, convert_scalar_to_number); + zval_dtor(op); + + if (Z_TYPE(dst) == IS_LONG || Z_TYPE(dst) == IS_DOUBLE) { + ZVAL_COPY_VALUE(op, &dst); + } else { + ZVAL_LONG(op, 1); + } + } break; } } @@ -215,17 +246,17 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ break; \ case IS_OBJECT: \ ZVAL_COPY(&(holder), op); \ - convert_to_long_base(&(holder), 10); \ + _convert_scalar_to_number(&(holder), silent); \ if (UNEXPECTED(EG(exception))) { \ if (result != op1) { \ ZVAL_UNDEF(result); \ } \ return FAILURE; \ } \ - if (Z_TYPE(holder) == IS_LONG) { \ + if (Z_TYPE(holder) == IS_LONG || Z_TYPE(holder) == IS_DOUBLE) { \ if (op == result) { \ zval_ptr_dtor(op); \ - ZVAL_LONG(op, Z_LVAL(holder)); \ + ZVAL_COPY(op, &(holder)); \ } else { \ (op) = &(holder); \ } \ @@ -237,26 +268,6 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ /* }}} */ -/* {{{ convert_object_to_type: dst will be either ctype or UNDEF */ -#define convert_object_to_type(op, dst, ctype, conv_func) \ - ZVAL_UNDEF(dst); \ - if (Z_OBJ_HT_P(op)->cast_object) { \ - if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) { \ - zend_error(E_RECOVERABLE_ERROR, \ - "Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\ - zend_get_type_by_const(ctype)); \ - } \ - } else if (Z_OBJ_HT_P(op)->get) { \ - zval *newop = Z_OBJ_HT_P(op)->get(op, dst); \ - if (Z_TYPE_P(newop) != IS_OBJECT) { \ - /* for safety - avoid loop */ \ - ZVAL_COPY_VALUE(dst, newop); \ - conv_func(dst); \ - } \ - } - -/* }}} */ - #define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, op, op_func) \ do { \ if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \ |