Skip to content

Commit 2b38384

Browse files
committed
Fix handling of references in zval_try_get_long()
This API can't handle references, yet everyone keeps forgetting that it can't and that you should DEREF upfront. Fix every type of this issue once and for all by moving the reference handling to this Zend API. Closes GH-18761.
1 parent 111072a commit 2b38384

File tree

6 files changed

+27
-8
lines changed

6 files changed

+27
-8
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ PHP NEWS
1212
released on bailout). (DanielEScherzer and ilutov)
1313
. Fixed GH-18695 (zend_ast_export() - float number is not preserved).
1414
(Oleg Efimov)
15+
. Fix handling of references in zval_try_get_long(). (nielsdos)
1516

1617
- Curl:
1718
. Fix memory leak when setting a list via curl_setopt fails. (nielsdos)

Zend/zend_operators.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ static zend_always_inline zend_result zendi_try_convert_scalar_to_number(zval *o
378378
static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval *op, bool *failed) /* {{{ */
379379
{
380380
*failed = 0;
381+
try_again:
381382
switch (Z_TYPE_P(op)) {
382383
case IS_NULL:
383384
case IS_FALSE:
@@ -448,6 +449,14 @@ static zend_never_inline zend_long ZEND_FASTCALL zendi_try_get_long(const zval *
448449
case IS_ARRAY:
449450
*failed = 1;
450451
return 0;
452+
case IS_REFERENCE:
453+
op = Z_REFVAL_P(op);
454+
if (Z_TYPE_P(op) == IS_LONG) {
455+
return Z_LVAL_P(op);
456+
} else {
457+
goto try_again;
458+
}
459+
break;
451460
EMPTY_SWITCH_DEFAULT_CASE()
452461
}
453462
}

ext/intl/dateformat/dateformat_parse.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,12 +185,10 @@ PHP_METHOD(IntlDateFormatter, parseToCalendar)
185185
DATE_FORMAT_METHOD_FETCH_OBJECT;
186186

187187
if (z_parse_pos) {
188-
zval *z_parse_pos_tmp = z_parse_pos;
189-
ZVAL_DEREF(z_parse_pos_tmp);
190-
bool failed = false;
191-
zend_long long_parse_pos = zval_try_get_long(z_parse_pos_tmp, &failed);
188+
bool failed;
189+
zend_long long_parse_pos = zval_try_get_long(z_parse_pos, &failed);
192190
if (failed) {
193-
zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos_tmp));
191+
zend_argument_type_error(2, "must be of type int, %s given", zend_zval_value_name(z_parse_pos));
194192
RETURN_THROWS();
195193
}
196194
if (ZEND_LONG_INT_OVFL(long_parse_pos)) {

ext/mbstring/mbstring.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3930,7 +3930,7 @@ static uint32_t *make_conversion_map(HashTable *target_hash, size_t *conversion_
39303930
uint32_t *mapelm = convmap;
39313931

39323932
ZEND_HASH_FOREACH_VAL(target_hash, hash_entry) {
3933-
bool failed = true;
3933+
bool failed;
39343934
zend_long tmp = zval_try_get_long(hash_entry, &failed);
39353935
if (failed) {
39363936
efree(convmap);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
mb_encode_numericentity() reference handling
3+
--EXTENSIONS--
4+
mbstring
5+
--FILE--
6+
<?php
7+
$n = 0;
8+
$convmap = [&$n, 0x1FFFFF, 0, 0x10FFFF];
9+
var_dump(mb_encode_numericentity("", $convmap, "utf8"));
10+
?>
11+
--EXPECT--
12+
string(0) ""

ext/pcntl/pcntl.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -874,8 +874,7 @@ static bool php_pcntl_set_user_signal_infos(
874874

875875
zval *user_signal_no;
876876
ZEND_HASH_FOREACH_VAL(user_signals, user_signal_no) {
877-
bool failed = true;
878-
ZVAL_DEREF(user_signal_no);
877+
bool failed;
879878
zend_long tmp = zval_try_get_long(user_signal_no, &failed);
880879

881880
if (failed) {

0 commit comments

Comments
 (0)