Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b2b2b43

Browse files
committed
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.
1 parent efcbea4 commit b2b2b43

25 files changed

Lines changed: 134 additions & 42 deletions

NEWS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ PHP NEWS
2727
function). (Li-Wen Hsu)
2828
. Fixed bug #54043 (Remove inconsitency of internal exceptions and user
2929
defined exceptions). (Nikita)
30+
. Fixed bug #53033 (Mathematical operations convert objects to integers).
31+
(Nikita)
32+
. Fixed bug #73108 (Internal class cast handler uses integer instead of
33+
float). (Nikita)
3034

3135
- BCMath:
3236
. Fixed bug #66364 (BCMath bcmul ignores scale parameter). (cmb)
@@ -132,6 +136,9 @@ PHP NEWS
132136
. Fixed bug #74941 (session fails to start after having headers sent).
133137
(morozov)
134138

139+
- SimpleXML:
140+
. Fixed bug #54973 (SimpleXML casts integers wrong). (Nikita)
141+
135142
- SOAP:
136143
. Fixed bug #75464 (Wrong reflection on SoapClient::__setSoapHeaders). (villfa)
137144

UPGRADING

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Core:
3131

3232
BCMath:
3333
. All warnings thrown by BCMath functions are now using PHP's error handling.
34-
Formerly some warnings have directly been written to stderr.
34+
Formerly some warnings have directly been written to stderr.
3535
. bcmul() and bcpow() now return numbers with the requested scale. Formerly,
3636
the returned numbers may have omitted trailing decimal zeroes.
3737

@@ -40,6 +40,11 @@ SPL:
4040
executed. Previously all autoloaders were executed and exceptions were
4141
chained.
4242

43+
SimpleXML:
44+
. Mathematic operations involving SimpleXML objects will now treat the text as
45+
an integer or float, whichever is more appropriate. Previously values were
46+
treated as integers unconditionally.
47+
4348
Standard:
4449
. getimagesize() and related functions now report the mime type of BMP images
4550
as image/bmp instead of image/x-ms-bmp, since the former has been registered
@@ -140,7 +145,7 @@ JSON:
140145
. Support for Birdstep has been removed.
141146

142147
ZIP:
143-
. Bunled libzip has been dropped,
148+
. Bundled libzip has been dropped,
144149
system library is now required.
145150

146151
========================================

UPGRADING.INTERNALS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ PHP 7.3 INTERNALS UPGRADE NOTES
1010
g. zend_get_parameters()
1111
h. zend_register_persistent_resource()
1212
i. RAND_RANGE()
13+
j. cast_object() with _IS_NUMBER
1314

1415
2. Build system changes
1516
a. Unix build system changes
@@ -86,6 +87,10 @@ PHP 7.3 INTERNALS UPGRADE NOTES
8687
i. The RANGE_RANGE() macro has been removed. php_mt_rand_range() should be
8788
used instead.
8889

90+
j. The cast_object() object handler now also accepts the _IS_NUMBER type. The
91+
handler should return either an integer or float value in this case,
92+
whichever is more appropriate.
93+
8994
========================
9095
2. Build system changes
9196
========================

Zend/tests/add_002.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ var_dump($c);
2020
echo "Done\n";
2121
?>
2222
--EXPECTF--
23-
Notice: Object of class stdClass could not be converted to int in %sadd_002.php on line %d
23+
Notice: Object of class stdClass could not be converted to number in %sadd_002.php on line %d
2424

2525
Exception: Unsupported operand types
2626

27-
Notice: Object of class stdClass could not be converted to int in %s on line %d
27+
Notice: Object of class stdClass could not be converted to number in %s on line %d
2828

2929
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
3030
Stack trace:

Zend/tests/add_003.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ var_dump($c);
2020
echo "Done\n";
2121
?>
2222
--EXPECTF--
23-
Notice: Object of class stdClass could not be converted to int in %sadd_003.php on line %d
23+
Notice: Object of class stdClass could not be converted to number in %sadd_003.php on line %d
2424

2525
Exception: Unsupported operand types
2626

27-
Notice: Object of class stdClass could not be converted to int in %s on line %d
27+
Notice: Object of class stdClass could not be converted to number in %s on line %d
2828

2929
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
3030
Stack trace:

Zend/tests/assert/indirect_var_access_misoptimization.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ test();
1717
--EXPECTF--
1818
Deprecated: assert(): Calling assert() with a string argument is deprecated in %s on line %d
1919

20-
Notice: Object of class stdClass could not be converted to int in %s on line %d
20+
Notice: Object of class stdClass could not be converted to number in %s on line %d
2121
int(2)

Zend/tests/bug73337.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class d { function __destruct() { throw new Exception; } }
66
try { new d + new d; } catch (Exception $e) { print "Exception properly caught\n"; }
77
?>
88
--EXPECTF--
9-
Notice: Object of class d could not be converted to int in %sbug73337.php on line 3
9+
Notice: Object of class d could not be converted to number in %sbug73337.php on line 3
1010

11-
Notice: Object of class d could not be converted to int in %sbug73337.php on line 3
11+
Notice: Object of class d could not be converted to number in %sbug73337.php on line 3
1212
Exception properly caught

Zend/zend_API.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
126126
return "array";
127127
case IS_VOID:
128128
return "void";
129+
case _IS_NUMBER:
130+
return "number";
129131
default:
130132
return "unknown";
131133
}

Zend/zend_object_handlers.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,11 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
16981698
zend_error(E_NOTICE, "Object of class %s could not be converted to float", ZSTR_VAL(ce->name));
16991699
ZVAL_DOUBLE(writeobj, 1);
17001700
return SUCCESS;
1701+
case _IS_NUMBER:
1702+
ce = Z_OBJCE_P(readobj);
1703+
zend_error(E_NOTICE, "Object of class %s could not be converted to number", ZSTR_VAL(ce->name));
1704+
ZVAL_LONG(writeobj, 1);
1705+
return SUCCESS;
17011706
default:
17021707
ZVAL_NULL(writeobj);
17031708
break;

Zend/zend_operators.c

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,26 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* {
136136
}
137137
/* }}} */
138138

139+
/* {{{ convert_object_to_type: dst will be either ctype or UNDEF */
140+
#define convert_object_to_type(op, dst, ctype, conv_func) \
141+
ZVAL_UNDEF(dst); \
142+
if (Z_OBJ_HT_P(op)->cast_object) { \
143+
if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) { \
144+
zend_error(E_RECOVERABLE_ERROR, \
145+
"Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\
146+
zend_get_type_by_const(ctype)); \
147+
} \
148+
} else if (Z_OBJ_HT_P(op)->get) { \
149+
zval *newop = Z_OBJ_HT_P(op)->get(op, dst); \
150+
if (Z_TYPE_P(newop) != IS_OBJECT) { \
151+
/* for safety - avoid loop */ \
152+
ZVAL_COPY_VALUE(dst, newop); \
153+
conv_func(dst); \
154+
} \
155+
}
156+
157+
/* }}} */
158+
139159
void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent) /* {{{ */
140160
{
141161
try_again:
@@ -172,7 +192,18 @@ void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent) /* {{{
172192
}
173193
break;
174194
case IS_OBJECT:
175-
convert_to_long_base(op, 10);
195+
{
196+
zval dst;
197+
198+
convert_object_to_type(op, &dst, _IS_NUMBER, convert_scalar_to_number);
199+
zval_dtor(op);
200+
201+
if (Z_TYPE(dst) == IS_LONG || Z_TYPE(dst) == IS_DOUBLE) {
202+
ZVAL_COPY_VALUE(op, &dst);
203+
} else {
204+
ZVAL_LONG(op, 1);
205+
}
206+
}
176207
break;
177208
}
178209
}
@@ -215,17 +246,17 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
215246
break; \
216247
case IS_OBJECT: \
217248
ZVAL_COPY(&(holder), op); \
218-
convert_to_long_base(&(holder), 10); \
249+
_convert_scalar_to_number(&(holder), silent); \
219250
if (UNEXPECTED(EG(exception))) { \
220251
if (result != op1) { \
221252
ZVAL_UNDEF(result); \
222253
} \
223254
return FAILURE; \
224255
} \
225-
if (Z_TYPE(holder) == IS_LONG) { \
256+
if (Z_TYPE(holder) == IS_LONG || Z_TYPE(holder) == IS_DOUBLE) { \
226257
if (op == result) { \
227258
zval_ptr_dtor(op); \
228-
ZVAL_LONG(op, Z_LVAL(holder)); \
259+
ZVAL_COPY(op, &(holder)); \
229260
} else { \
230261
(op) = &(holder); \
231262
} \
@@ -237,26 +268,6 @@ ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */
237268

238269
/* }}} */
239270

240-
/* {{{ convert_object_to_type: dst will be either ctype or UNDEF */
241-
#define convert_object_to_type(op, dst, ctype, conv_func) \
242-
ZVAL_UNDEF(dst); \
243-
if (Z_OBJ_HT_P(op)->cast_object) { \
244-
if (Z_OBJ_HT_P(op)->cast_object(op, dst, ctype) == FAILURE) { \
245-
zend_error(E_RECOVERABLE_ERROR, \
246-
"Object of class %s could not be converted to %s", ZSTR_VAL(Z_OBJCE_P(op)->name),\
247-
zend_get_type_by_const(ctype)); \
248-
} \
249-
} else if (Z_OBJ_HT_P(op)->get) { \
250-
zval *newop = Z_OBJ_HT_P(op)->get(op, dst); \
251-
if (Z_TYPE_P(newop) != IS_OBJECT) { \
252-
/* for safety - avoid loop */ \
253-
ZVAL_COPY_VALUE(dst, newop); \
254-
conv_func(dst); \
255-
} \
256-
}
257-
258-
/* }}} */
259-
260271
#define convert_op1_op2_long(op1, op1_lval, op2, op2_lval, result, op, op_func) \
261272
do { \
262273
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { \

0 commit comments

Comments
 (0)