Skip to content

Commit a92b3e5

Browse files
committed
Rework is_long_compatible function
1 parent cfee4e0 commit a92b3e5

File tree

4 files changed

+39
-25
lines changed

4 files changed

+39
-25
lines changed

Zend/Optimizer/sccp.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,14 @@ static inline int fetch_array_elem(zval **result, zval *op1, zval *op2) {
425425
case IS_LONG:
426426
*result = zend_hash_index_find(Z_ARR_P(op1), Z_LVAL_P(op2));
427427
return SUCCESS;
428-
case IS_DOUBLE:
429-
if (!is_long_compatible(Z_DVAL_P(op2))) {
428+
case IS_DOUBLE: {
429+
zend_long lval = zend_dval_to_lval(Z_DVAL_P(op2));
430+
if (!zend_is_long_compatible(Z_DVAL_P(op2), lval)) {
430431
return FAILURE;
431432
}
432-
*result = zend_hash_index_find(Z_ARR_P(op1), zend_dval_to_lval(Z_DVAL_P(op2)));
433+
*result = zend_hash_index_find(Z_ARR_P(op1), lval);
433434
return SUCCESS;
435+
}
434436
case IS_STRING:
435437
*result = zend_symtable_find(Z_ARR_P(op1), Z_STR_P(op2));
436438
return SUCCESS;
@@ -511,12 +513,14 @@ static inline int ct_eval_del_array_elem(zval *result, zval *key) {
511513
case IS_LONG:
512514
zend_hash_index_del(Z_ARR_P(result), Z_LVAL_P(key));
513515
break;
514-
case IS_DOUBLE:
515-
if (!is_long_compatible(Z_DVAL_P(key))) {
516+
case IS_DOUBLE: {
517+
zend_long lval = zend_dval_to_lval(Z_DVAL_P(key));
518+
if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) {
516519
return FAILURE;
517520
}
518-
zend_hash_index_del(Z_ARR_P(result), zend_dval_to_lval(Z_DVAL_P(key)));
521+
zend_hash_index_del(Z_ARR_P(result), lval);
519522
break;
523+
}
520524
case IS_STRING:
521525
zend_symtable_del(Z_ARR_P(result), Z_STR_P(key));
522526
break;
@@ -554,14 +558,16 @@ static inline int ct_eval_add_array_elem(zval *result, zval *value, zval *key) {
554558
SEPARATE_ARRAY(result);
555559
value = zend_hash_index_update(Z_ARR_P(result), Z_LVAL_P(key), value);
556560
break;
557-
case IS_DOUBLE:
561+
case IS_DOUBLE: {
562+
zend_long lval = zend_dval_to_lval(Z_DVAL_P(key));
558563
SEPARATE_ARRAY(result);
559-
if (!is_long_compatible(Z_DVAL_P(key))) {
564+
if (!zend_is_long_compatible(Z_DVAL_P(key), lval)) {
560565
return FAILURE;
561566
}
562567
value = zend_hash_index_update(
563-
Z_ARR_P(result), zend_dval_to_lval(Z_DVAL_P(key)), value);
568+
Z_ARR_P(result), lval, value);
564569
break;
570+
}
565571
case IS_STRING:
566572
SEPARATE_ARRAY(result);
567573
value = zend_symtable_update(Z_ARR_P(result), Z_STR_P(key), value);

Zend/zend_API.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -501,41 +501,44 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest,
501501
if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
502502
return 0;
503503
} else {
504+
zend_long lval = zend_dval_to_lval(Z_DVAL_P(arg));
504505
/* Manually check arg_num is not (uint32_t)-1, as otherwise its called by
505506
* zend_verify_weak_scalar_type_hint_no_sideeffect() */
506-
if (UNEXPECTED(!is_long_compatible(Z_DVAL_P(arg)) && arg_num != (uint32_t)-1)) {
507+
if (UNEXPECTED(!zend_is_long_compatible(Z_DVAL_P(arg), lval) && arg_num != (uint32_t)-1)) {
507508
zend_error(E_DEPRECATED, "Implicit conversion to int from non-compatible float %f", Z_DVAL_P(arg));
508509
if (UNEXPECTED(EG(exception))) {
509510
return 0;
510511
}
511512
}
512-
*dest = zend_dval_to_lval(Z_DVAL_P(arg));
513+
*dest = lval;
513514
}
514515
} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
515516
double d;
516517
zend_uchar type;
517518

518519
if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
519520
if (EXPECTED(type != 0)) {
521+
zend_long lval;
520522
if (UNEXPECTED(zend_isnan(d))) {
521523
return 0;
522524
}
523525
if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
524526
return 0;
525527
}
526528

529+
lval = zend_dval_to_lval(d);
527530
/* This only checks for a fractional part as if doesn't fit it already throws a TypeError
528531
* Manually check to get correct warning text mentioning string origin
529532
* Check arg_num is not (uint32_t)-1, as otherwise its called by
530533
* zend_verify_weak_scalar_type_hint_no_sideeffect() */
531-
if (UNEXPECTED(!is_long_compatible(d) && arg_num != (uint32_t)-1)) {
534+
if (UNEXPECTED(!zend_is_long_compatible(d, lval) && arg_num != (uint32_t)-1)) {
532535
zend_error(E_DEPRECATED, "Implicit conversion to int from non-compatible float-string %s",
533536
Z_STRVAL_P(arg));
534537
if (UNEXPECTED(EG(exception))) {
535538
return 0;
536539
}
537540
}
538-
*dest = zend_dval_to_lval(d);
541+
*dest = lval;
539542
} else {
540543
return 0;
541544
}

Zend/zend_operators.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,14 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(zval *op, bo
305305
return 1;
306306
case IS_DOUBLE: {
307307
double dval = Z_DVAL_P(op);
308-
if (!is_long_compatible(dval)) {
308+
zend_long lval = zend_dval_to_lval(dval);
309+
if (!zend_is_long_compatible(dval, lval)) {
309310
zend_error(E_DEPRECATED, "Implicit conversion to int from non-compatible float %f", dval);
310311
if (UNEXPECTED(EG(exception))) {
311312
*failed = 1;
312313
}
313314
}
314-
return zend_dval_to_lval(dval);
315+
return lval;
315316
}
316317
case IS_STRING:
317318
{
@@ -341,14 +342,15 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(zval *op, bo
341342
* We use use saturating conversion to emulate strtol()'s
342343
* behaviour.
343344
*/
344-
if (!is_long_compatible(dval)) {
345+
lval = zend_dval_to_lval_cap(dval);
346+
if (!zend_is_long_compatible(dval, lval)) {
345347
zend_error(E_DEPRECATED, "Implicit conversion to int from non-compatible float-string %s",
346348
Z_STRVAL_P(op));
347349
if (UNEXPECTED(EG(exception))) {
348350
*failed = 1;
349351
}
350352
}
351-
return zend_dval_to_lval_cap(dval);
353+
return lval;
352354
}
353355
}
354356
case IS_OBJECT:
@@ -824,14 +826,15 @@ ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(zval *op, bool is_lax) /* {{
824826
return Z_LVAL_P(op);
825827
case IS_DOUBLE: {
826828
double dval = Z_DVAL_P(op);
829+
zend_long lval = zend_dval_to_lval(dval);
827830
if (EXPECTED(!is_lax)) {
828-
if (!is_long_compatible(dval)) {
831+
if (!zend_is_long_compatible(dval, lval)) {
829832
zend_error(E_DEPRECATED, "Implicit conversion to int from non-compatible float %f", dval);
830833
// TODO Need to handle this here?
831834
//if (UNEXPECTED(EG(exception))) {}
832835
}
833836
}
834-
return zend_dval_to_lval(dval);
837+
return lval;
835838
}
836839
case IS_STRING:
837840
{
@@ -849,15 +852,16 @@ ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(zval *op, bool is_lax) /* {{
849852
* behaviour.
850853
*/
851854
/* Most usages are expected to not be (int) casts */
855+
lval = zend_dval_to_lval_cap(dval);
852856
if (EXPECTED(!is_lax)) {
853-
if (!is_long_compatible(dval)) {
857+
if (!zend_is_long_compatible(dval, lval)) {
854858
zend_error(E_DEPRECATED, "Implicit conversion to int from non-compatible float-string %s",
855859
Z_STRVAL_P(op));
856860
// TODO Need to handle this here?
857861
//if (UNEXPECTED(EG(exception))) {}
858862
}
859863
}
860-
return zend_dval_to_lval_cap(dval);
864+
return lval;
861865
}
862866
}
863867
case IS_ARRAY:

Zend/zend_operators.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,17 @@ static zend_always_inline zend_long zend_dval_to_lval_cap(double d)
134134
}
135135
/* }}} */
136136

137-
static zend_always_inline bool is_long_compatible(double d) {
138-
return ((double)(zend_long) d == d);
137+
static zend_always_inline bool zend_is_long_compatible(double d, zend_long l) {
138+
return ((double)l == d);
139139
}
140140

141141
static zend_always_inline zend_long zend_dval_to_lval_safe(double d)
142142
{
143-
if (!is_long_compatible(d)) {
143+
zend_long l = zend_dval_to_lval(d);
144+
if (!zend_is_long_compatible(d, l)) {
144145
zend_error(E_DEPRECATED, "Implicit conversion to int from non-compatible float %f", d);
145146
}
146-
return zend_dval_to_lval(d);
147+
return l;
147148
}
148149

149150
#define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9')

0 commit comments

Comments
 (0)