summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS7
-rw-r--r--UPGRADING9
-rw-r--r--UPGRADING.INTERNALS5
-rw-r--r--Zend/tests/add_002.phpt4
-rw-r--r--Zend/tests/add_003.phpt4
-rw-r--r--Zend/tests/assert/indirect_var_access_misoptimization.phpt2
-rw-r--r--Zend/tests/bug73337.phpt4
-rw-r--r--Zend/zend_API.c2
-rw-r--r--Zend/zend_object_handlers.c5
-rw-r--r--Zend/zend_operators.c59
-rw-r--r--Zend/zend_types.h1
-rw-r--r--ext/com_dotnet/com_handlers.c1
-rw-r--r--ext/gmp/gmp.c8
-rw-r--r--ext/intl/tests/bug48227.phpt2
-rw-r--r--ext/simplexml/simplexml.c3
-rw-r--r--ext/simplexml/tests/bug53033.phpt21
-rw-r--r--ext/simplexml/tests/bug54973.phpt21
-rw-r--r--ext/standard/tests/math/abs_variation.phpt4
-rw-r--r--ext/standard/tests/math/ceil_variation1.phpt2
-rw-r--r--ext/standard/tests/math/floor_variation1.phpt2
-rw-r--r--ext/standard/tests/math/pow_variation1.phpt2
-rw-r--r--ext/standard/tests/math/pow_variation1_64bit.phpt2
-rw-r--r--ext/standard/tests/math/pow_variation2.phpt2
-rw-r--r--ext/standard/tests/math/round_variation1.phpt2
-rw-r--r--ext/tidy/tidy.c2
25 files changed, 134 insertions, 42 deletions
diff --git a/NEWS b/NEWS
index 3757f65384..e8fc786555 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,10 @@ PHP NEWS
function). (Li-Wen Hsu)
. Fixed bug #54043 (Remove inconsitency of internal exceptions and user
defined exceptions). (Nikita)
+ . Fixed bug #53033 (Mathematical operations convert objects to integers).
+ (Nikita)
+ . Fixed bug #73108 (Internal class cast handler uses integer instead of
+ float). (Nikita)
- BCMath:
. Fixed bug #66364 (BCMath bcmul ignores scale parameter). (cmb)
@@ -132,6 +136,9 @@ PHP NEWS
. Fixed bug #74941 (session fails to start after having headers sent).
(morozov)
+- SimpleXML:
+ . Fixed bug #54973 (SimpleXML casts integers wrong). (Nikita)
+
- SOAP:
. Fixed bug #75464 (Wrong reflection on SoapClient::__setSoapHeaders). (villfa)
diff --git a/UPGRADING b/UPGRADING
index 85d74a02c5..3565c28a96 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -31,7 +31,7 @@ Core:
BCMath:
. All warnings thrown by BCMath functions are now using PHP's error handling.
- Formerly some warnings have directly been written to stderr.
+ Formerly some warnings have directly been written to stderr.
. bcmul() and bcpow() now return numbers with the requested scale. Formerly,
the returned numbers may have omitted trailing decimal zeroes.
@@ -40,6 +40,11 @@ SPL:
executed. Previously all autoloaders were executed and exceptions were
chained.
+SimpleXML:
+ . Mathematic operations involving SimpleXML objects will now treat the text as
+ an integer or float, whichever is more appropriate. Previously values were
+ treated as integers unconditionally.
+
Standard:
. getimagesize() and related functions now report the mime type of BMP images
as image/bmp instead of image/x-ms-bmp, since the former has been registered
@@ -140,7 +145,7 @@ JSON:
. Support for Birdstep has been removed.
ZIP:
- . Bunled libzip has been dropped,
+ . Bundled libzip has been dropped,
system library is now required.
========================================
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index c5a41f2198..7b03440a53 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -10,6 +10,7 @@ PHP 7.3 INTERNALS UPGRADE NOTES
g. zend_get_parameters()
h. zend_register_persistent_resource()
i. RAND_RANGE()
+ j. cast_object() with _IS_NUMBER
2. Build system changes
a. Unix build system changes
@@ -86,6 +87,10 @@ PHP 7.3 INTERNALS UPGRADE NOTES
i. The RANGE_RANGE() macro has been removed. php_mt_rand_range() should be
used instead.
+ j. The cast_object() object handler now also accepts the _IS_NUMBER type. The
+ handler should return either an integer or float value in this case,
+ whichever is more appropriate.
+
========================
2. Build system changes
========================
diff --git a/Zend/tests/add_002.phpt b/Zend/tests/add_002.phpt
index 4d804fe3e8..1e9148ffa5 100644
--- a/Zend/tests/add_002.phpt
+++ b/Zend/tests/add_002.phpt
@@ -20,11 +20,11 @@ var_dump($c);
echo "Done\n";
?>
--EXPECTF--
-Notice: Object of class stdClass could not be converted to int in %sadd_002.php on line %d
+Notice: Object of class stdClass could not be converted to number in %sadd_002.php on line %d
Exception: Unsupported operand types
-Notice: Object of class stdClass could not be converted to int in %s on line %d
+Notice: Object of class stdClass could not be converted to number in %s on line %d
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
Stack trace:
diff --git a/Zend/tests/add_003.phpt b/Zend/tests/add_003.phpt
index a3705479e2..cc2a0dd1a7 100644
--- a/Zend/tests/add_003.phpt
+++ b/Zend/tests/add_003.phpt
@@ -20,11 +20,11 @@ var_dump($c);
echo "Done\n";
?>
--EXPECTF--
-Notice: Object of class stdClass could not be converted to int in %sadd_003.php on line %d
+Notice: Object of class stdClass could not be converted to number in %sadd_003.php on line %d
Exception: Unsupported operand types
-Notice: Object of class stdClass could not be converted to int in %s on line %d
+Notice: Object of class stdClass could not be converted to number in %s on line %d
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
Stack trace:
diff --git a/Zend/tests/assert/indirect_var_access_misoptimization.phpt b/Zend/tests/assert/indirect_var_access_misoptimization.phpt
index 6c05a8c607..02327f30c0 100644
--- a/Zend/tests/assert/indirect_var_access_misoptimization.phpt
+++ b/Zend/tests/assert/indirect_var_access_misoptimization.phpt
@@ -17,5 +17,5 @@ test();
--EXPECTF--
Deprecated: assert(): Calling assert() with a string argument is deprecated in %s on line %d
-Notice: Object of class stdClass could not be converted to int in %s on line %d
+Notice: Object of class stdClass could not be converted to number in %s on line %d
int(2)
diff --git a/Zend/tests/bug73337.phpt b/Zend/tests/bug73337.phpt
index 9eff18e643..53ce963c52 100644
--- a/Zend/tests/bug73337.phpt
+++ b/Zend/tests/bug73337.phpt
@@ -6,7 +6,7 @@ class d { function __destruct() { throw new Exception; } }
try { new d + new d; } catch (Exception $e) { print "Exception properly caught\n"; }
?>
--EXPECTF--
-Notice: Object of class d could not be converted to int in %sbug73337.php on line 3
+Notice: Object of class d could not be converted to number in %sbug73337.php on line 3
-Notice: Object of class d could not be converted to int in %sbug73337.php on line 3
+Notice: Object of class d could not be converted to number in %sbug73337.php on line 3
Exception properly caught
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 357368f88d..7e19683094 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -126,6 +126,8 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
return "array";
case IS_VOID:
return "void";
+ case _IS_NUMBER:
+ return "number";
default:
return "unknown";
}
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 98ae806adb..33db03636c 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -1698,6 +1698,11 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
zend_error(E_NOTICE, "Object of class %s could not be converted to float", ZSTR_VAL(ce->name));
ZVAL_DOUBLE(writeobj, 1);
return SUCCESS;
+ case _IS_NUMBER:
+ ce = Z_OBJCE_P(readobj);
+ zend_error(E_NOTICE, "Object of class %s could not be converted to number", ZSTR_VAL(ce->name));
+ ZVAL_LONG(writeobj, 1);
+ return SUCCESS;
default:
ZVAL_NULL(writeobj);
break;
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)) { \
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index 0ccc92425c..a0abe5acb7 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -386,6 +386,7 @@ struct _zend_ast_ref {
#define IS_CALLABLE 17
#define IS_ITERABLE 18
#define IS_VOID 19
+#define _IS_NUMBER 20
static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
return pz->u1.v.type;
diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c
index d28398315d..e6d62c3640 100644
--- a/ext/com_dotnet/com_handlers.c
+++ b/ext/com_dotnet/com_handlers.c
@@ -484,6 +484,7 @@ static int com_object_cast(zval *readobj, zval *writeobj, int type)
switch(type) {
case IS_LONG:
+ case _IS_NUMBER:
vt = VT_INT;
break;
case IS_DOUBLE:
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index 85a2258e19..5783e0d02f 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -425,6 +425,14 @@ static int gmp_cast_object(zval *readobj, zval *writeobj, int type) /* {{{ */
gmpnum = GET_GMP_FROM_ZVAL(readobj);
ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum));
return SUCCESS;
+ case _IS_NUMBER:
+ gmpnum = GET_GMP_FROM_ZVAL(readobj);
+ if (mpz_fits_slong_p(gmpnum)) {
+ ZVAL_LONG(writeobj, mpz_get_si(gmpnum));
+ } else {
+ ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum));
+ }
+ return SUCCESS;
default:
return FAILURE;
}
diff --git a/ext/intl/tests/bug48227.phpt b/ext/intl/tests/bug48227.phpt
index 0ac0d5e555..42a4ffaf86 100644
--- a/ext/intl/tests/bug48227.phpt
+++ b/ext/intl/tests/bug48227.phpt
@@ -17,5 +17,5 @@ string(1) "0"
string(1) "1"
string(1) "0"
-Notice: Object of class NumberFormatter could not be converted to int in %s on line %d
+Notice: Object of class NumberFormatter could not be converted to number in %s on line %d
string(1) "1"
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 66ac14ad88..715b31f420 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -1857,6 +1857,9 @@ static int cast_object(zval *object, int type, char *contents)
case IS_DOUBLE:
convert_to_double(object);
break;
+ case _IS_NUMBER:
+ convert_scalar_to_number(object);
+ break;
default:
return FAILURE;
}
diff --git a/ext/simplexml/tests/bug53033.phpt b/ext/simplexml/tests/bug53033.phpt
new file mode 100644
index 0000000000..626022cd54
--- /dev/null
+++ b/ext/simplexml/tests/bug53033.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #53033: Mathematical operations convert objects to integers
+--FILE--
+<?php
+
+$x = simplexml_load_string('<x>2.5</x>');
+var_dump($x*1);
+// type of other operand is irrelevant
+var_dump($x*1.0);
+
+// strings behave differently
+$y = '2.5';
+var_dump($y*1);
+var_dump((string)$x*1);
+
+?>
+--EXPECT--
+float(2.5)
+float(2.5)
+float(2.5)
+float(2.5)
diff --git a/ext/simplexml/tests/bug54973.phpt b/ext/simplexml/tests/bug54973.phpt
new file mode 100644
index 0000000000..29daaed788
--- /dev/null
+++ b/ext/simplexml/tests/bug54973.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #54973: SimpleXML casts integers wrong
+--FILE--
+<?php
+$xml = simplexml_load_string("<xml><number>9223372036854775808</number></xml>");
+
+var_dump($xml->number);
+
+$int = $xml->number / 1024 / 1024 / 1024;
+var_dump($int);
+
+$double = (double) $xml->number / 1024 / 1024 / 1024;
+var_dump($double);
+?>
+--EXPECT--
+object(SimpleXMLElement)#2 (1) {
+ [0]=>
+ string(19) "9223372036854775808"
+}
+float(8589934592)
+float(8589934592)
diff --git a/ext/standard/tests/math/abs_variation.phpt b/ext/standard/tests/math/abs_variation.phpt
index 6df1e6b55c..ed9085446b 100644
--- a/ext/standard/tests/math/abs_variation.phpt
+++ b/ext/standard/tests/math/abs_variation.phpt
@@ -121,7 +121,7 @@ int(0)
-- Iteration 13 --
-Notice: Object of class classA could not be converted to int in %s on line %d
+Notice: Object of class classA could not be converted to number in %s on line %d
int(1)
-- Iteration 14 --
@@ -132,4 +132,4 @@ int(0)
-- Iteration 16 --
int(%d)
-===Done=== \ No newline at end of file
+===Done===
diff --git a/ext/standard/tests/math/ceil_variation1.phpt b/ext/standard/tests/math/ceil_variation1.phpt
index 7c1f859277..35a9e1d4a3 100644
--- a/ext/standard/tests/math/ceil_variation1.phpt
+++ b/ext/standard/tests/math/ceil_variation1.phpt
@@ -114,7 +114,7 @@ float(0)
-- Iteration 13 --
-Notice: Object of class classA could not be converted to int in %s on line %d
+Notice: Object of class classA could not be converted to number in %s on line %d
float(1)
-- Iteration 14 --
diff --git a/ext/standard/tests/math/floor_variation1.phpt b/ext/standard/tests/math/floor_variation1.phpt
index baba53aab4..fcb895164a 100644
--- a/ext/standard/tests/math/floor_variation1.phpt
+++ b/ext/standard/tests/math/floor_variation1.phpt
@@ -114,7 +114,7 @@ float(0)
-- Iteration 13 --
-Notice: Object of class classA could not be converted to int in %s on line %d
+Notice: Object of class classA could not be converted to number in %s on line %d
float(1)
-- Iteration 14 --
diff --git a/ext/standard/tests/math/pow_variation1.phpt b/ext/standard/tests/math/pow_variation1.phpt
index c744c4eb9d..3b1befe16b 100644
--- a/ext/standard/tests/math/pow_variation1.phpt
+++ b/ext/standard/tests/math/pow_variation1.phpt
@@ -172,7 +172,7 @@ int(0)
-- Iteration 23 --
-Notice: Object of class classA could not be converted to int in %s on line %d
+Notice: Object of class classA could not be converted to number in %s on line %d
int(1)
-- Iteration 24 --
diff --git a/ext/standard/tests/math/pow_variation1_64bit.phpt b/ext/standard/tests/math/pow_variation1_64bit.phpt
index ea2ae45d18..35f9942490 100644
--- a/ext/standard/tests/math/pow_variation1_64bit.phpt
+++ b/ext/standard/tests/math/pow_variation1_64bit.phpt
@@ -172,7 +172,7 @@ int(0)
-- Iteration 23 --
-Notice: Object of class classA could not be converted to int in %s on line %d
+Notice: Object of class classA could not be converted to number in %s on line %d
int(1)
-- Iteration 24 --
diff --git a/ext/standard/tests/math/pow_variation2.phpt b/ext/standard/tests/math/pow_variation2.phpt
index 36b085b647..d93a952dbe 100644
--- a/ext/standard/tests/math/pow_variation2.phpt
+++ b/ext/standard/tests/math/pow_variation2.phpt
@@ -168,7 +168,7 @@ float(1)
-- Iteration 23 --
-Notice: Object of class classA could not be converted to int in %s on line %d
+Notice: Object of class classA could not be converted to number in %s on line %d
float(20.3)
-- Iteration 24 --
diff --git a/ext/standard/tests/math/round_variation1.phpt b/ext/standard/tests/math/round_variation1.phpt
index c89dd6818a..c1883a5c1b 100644
--- a/ext/standard/tests/math/round_variation1.phpt
+++ b/ext/standard/tests/math/round_variation1.phpt
@@ -159,7 +159,7 @@ float(0)
-- Iteration 23 --
-Notice: Object of class classA could not be converted to int in %s on line %d
+Notice: Object of class classA could not be converted to number in %s on line %d
float(1)
-- Iteration 24 --
diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c
index 63f8c968c3..355e4f0f1e 100644
--- a/ext/tidy/tidy.c
+++ b/ext/tidy/tidy.c
@@ -733,6 +733,7 @@ static int tidy_doc_cast_handler(zval *in, zval *out, int type)
switch (type) {
case IS_LONG:
+ case _IS_NUMBER:
ZVAL_LONG(out, 0);
break;
@@ -766,6 +767,7 @@ static int tidy_node_cast_handler(zval *in, zval *out, int type)
switch(type) {
case IS_LONG:
+ case _IS_NUMBER:
ZVAL_LONG(out, 0);
break;