File tree Expand file tree Collapse file tree 8 files changed +230
-2
lines changed
tests/type_coercion/float_to_int Expand file tree Collapse file tree 8 files changed +230
-2
lines changed Original file line number Diff line number Diff line change 1+ --TEST--
2+ Non rep float string to int conversions should not crash when modified
3+ --FILE--
4+ <?php
5+ set_error_handler (function ($ errno , $ errstr ) {
6+ global $ b ;
7+ $ b = null ;
8+ echo $ errstr , "\n" ;
9+ });
10+
11+ $ a = "1.0E+ " . rand (40 ,42 );
12+ $ b = &$ a ;
13+ var_dump ($ b | 1 );
14+
15+ ?>
16+ --EXPECTF--
17+ non-representable float-string 1.0E+4%d was cast to int
18+ Implicit conversion from float-string "1.0E+4%d" to int loses precision
19+ int(9223372036854775807)
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Non rep float string to int conversions should not crash when modified
3+ --FILE--
4+ <?php
5+
6+ set_error_handler (function ($ errno , $ errstr ) {
7+ global $ ary ;
8+ $ ary = null ;
9+ echo $ errstr , "\n" ;
10+ });
11+
12+ $ ary = [rand ()];
13+ unset($ ary [1.0E+42 ]);
14+
15+ ?>
16+ --EXPECT--
17+ non-representable float 1.0E+42 was cast to int
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Non rep float string to int conversions should not crash when modified
3+ --FILE--
4+ <?php
5+
6+ set_error_handler (function ($ errno , $ errstr ) {
7+ global $ ary ;
8+ $ ary = null ;
9+ echo $ errstr , "\n" ;
10+ });
11+
12+ $ ary = [rand ()];
13+ var_dump (isset ($ ary [1.0E+42 ]));
14+
15+ ?>
16+ --EXPECT--
17+ non-representable float 1.0E+42 was cast to int
18+ bool(false)
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Non rep float string to int conversions should not crash when modified
3+ --FILE--
4+ <?php
5+
6+ set_error_handler (function ($ errno , $ errstr ) {
7+ global $ ary ;
8+ $ ary = null ;
9+ echo $ errstr , "\n" ;
10+ });
11+
12+ $ ary = [rand ()];
13+ var_dump (\array_key_exists (1.0E+42 , $ ary ));
14+
15+ ?>
16+ --EXPECT--
17+ non-representable float 1.0E+42 was cast to int
18+ bool(false)
Original file line number Diff line number Diff line change @@ -3241,7 +3241,17 @@ static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable
32413241 zend_ulong hval ;
32423242
32433243 if (Z_TYPE_P (offset ) == IS_DOUBLE ) {
3244+ /* The array may be destroyed while throwing a warning in case the float is not representable as an int.
3245+ * Temporarily increase the refcount to detect this situation. */
3246+ GC_TRY_ADDREF (ht );
32443247 hval = zend_dval_to_lval_safe (Z_DVAL_P (offset ));
3248+ if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE ) && !GC_DELREF (ht )) {
3249+ zend_array_destroy (ht );
3250+ return NULL ;
3251+ }
3252+ if (EG (exception )) {
3253+ return NULL ;
3254+ }
32453255num_idx :
32463256 return zend_hash_index_find (ht , hval );
32473257 } else if (Z_TYPE_P (offset ) == IS_NULL ) {
@@ -3380,7 +3390,17 @@ static zend_never_inline bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable
33803390 key = Z_REFVAL_P (key );
33813391 goto try_again ;
33823392 } else if (Z_TYPE_P (key ) == IS_DOUBLE ) {
3393+ /* The array may be destroyed while throwing a warning in case the float is not representable as an int.
3394+ * Temporarily increase the refcount to detect this situation. */
3395+ GC_TRY_ADDREF (ht );
33833396 hval = zend_dval_to_lval_safe (Z_DVAL_P (key ));
3397+ if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE ) && !GC_DELREF (ht )) {
3398+ zend_array_destroy (ht );
3399+ return false;
3400+ }
3401+ if (EG (exception )) {
3402+ return false;
3403+ }
33843404 goto num_key ;
33853405 } else if (Z_TYPE_P (key ) == IS_FALSE ) {
33863406 hval = 0 ;
Original file line number Diff line number Diff line change @@ -415,6 +415,8 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval *
415415 zend_error (E_WARNING , "A non-numeric value encountered" );
416416 if (UNEXPECTED (EG (exception ))) {
417417 * failed = 1 ;
418+ zend_tmp_string_release (op_str );
419+ return 0 ;
418420 }
419421 }
420422 if (EXPECTED (type == IS_LONG )) {
@@ -425,14 +427,18 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval *
425427 * We use use saturating conversion to emulate strtol()'s
426428 * behaviour.
427429 */
430+ if (op_str == NULL ) {
431+ /* zend_dval_to_lval_cap() can emit a warning so always do the copy here */
432+ op_str = zend_string_copy (Z_STR_P (op ));
433+ }
428434 lval = zend_dval_to_lval_cap (dval );
429435 if (!zend_is_long_compatible (dval , lval )) {
430- zend_incompatible_string_to_long_error (op_str ? op_str : Z_STR_P ( op ) );
436+ zend_incompatible_string_to_long_error (op_str );
431437 if (UNEXPECTED (EG (exception ))) {
432438 * failed = 1 ;
433439 }
434440 }
435- zend_tmp_string_release (op_str );
441+ zend_string_release (op_str );
436442 return lval ;
437443 }
438444 }
Original file line number Diff line number Diff line change @@ -6751,7 +6751,17 @@ ZEND_VM_C_LABEL(num_index_dim):
67516751 offset = Z_REFVAL_P (offset );
67526752 ZEND_VM_C_GOTO (offset_again );
67536753 } else if (Z_TYPE_P (offset ) == IS_DOUBLE ) {
6754+ /* The array may be destroyed while throwing a warning in case the float is not representable as an int.
6755+ * Temporarily increase the refcount to detect this situation. */
6756+ GC_TRY_ADDREF (ht );
67546757 hval = zend_dval_to_lval_safe (Z_DVAL_P (offset ));
6758+ if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE ) && !GC_DELREF (ht )) {
6759+ zend_array_destroy (ht );
6760+ break ;
6761+ }
6762+ if (EG (exception )) {
6763+ break ;
6764+ }
67556765 ZEND_VM_C_GOTO (num_index_dim );
67566766 } else if (Z_TYPE_P (offset ) == IS_NULL ) {
67576767 key = ZSTR_EMPTY_ALLOC ();
You can’t perform that action at this time.
0 commit comments