summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2017-12-25 13:18:45 +0100
committerNikita Popov <nikita.ppv@gmail.com>2017-12-26 12:39:06 +0100
commitb2b2b437af5495dcb2016be6e45567ed826cb87e (patch)
tree7cf17c011f6b9c272eebf184fa47d5c35f455b2f /Zend/zend_operators.c
parentefcbea43455ca4e27ec6fc5ce2f3a740a981247e (diff)
downloadphp-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.c59
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)) { \