Skip to content

Commit a1564b1

Browse files
Avoid addref/delref where possible
1 parent 34132a7 commit a1564b1

File tree

3 files changed

+49
-81
lines changed

3 files changed

+49
-81
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
No UAF on null offset
3+
--FILE--
4+
<?php
5+
set_error_handler(function($errno, $errstr) {
6+
global $ary;
7+
$ary = null;
8+
echo $errstr;
9+
});
10+
11+
$ary[null] = 1;
12+
13+
echo "\nSuccess\n";
14+
?>
15+
--EXPECTF--
16+
Using null as an array offset is deprecated, use an empty string instead
17+
Success

Zend/zend_execute.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,9 +2631,7 @@ static zend_never_inline uint8_t slow_index_convert(HashTable *ht, const zval *d
26312631
case IS_NULL:
26322632
/* The array may be destroyed while throwing the notice.
26332633
* Temporarily increase the refcount to detect this situation. */
2634-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2635-
GC_ADDREF(ht);
2636-
}
2634+
GC_TRY_ADDREF(ht);
26372635

26382636
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
26392637

@@ -2718,9 +2716,7 @@ static zend_never_inline uint8_t slow_index_convert_w(HashTable *ht, const zval
27182716
case IS_NULL:
27192717
/* The array may be destroyed while throwing the notice.
27202718
* Temporarily increase the refcount to detect this situation. */
2721-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2722-
GC_ADDREF(ht);
2723-
}
2719+
GC_TRY_ADDREF(ht);
27242720

27252721
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
27262722

@@ -3226,9 +3222,7 @@ static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable
32263222
null_undef_idx:
32273223
/* The array may be destroyed while throwing the notice.
32283224
* Temporarily increase the refcount to detect this situation. */
3229-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
3230-
GC_ADDREF(ht);
3231-
}
3225+
GC_TRY_ADDREF(ht);
32323226

32333227
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
32343228

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 29 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -500,33 +500,16 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_r_helper(zend_array *ht, zval *dim,
500500
}
501501
ZEND_FALLTHROUGH;
502502
case IS_NULL:
503-
/* The array may be destroyed while throwing the notice.
504-
* Temporarily increase the refcount to detect this situation. */
505-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
506-
GC_ADDREF(ht);
503+
retval = zend_hash_find(ht, ZSTR_EMPTY_ALLOC());
504+
if (!retval) {
505+
ZVAL_NULL(result);
506+
} else {
507+
ZVAL_COPY_DEREF(result, retval);
507508
}
508-
execute_data = EG(current_execute_data);
509-
opline = EX(opline);
509+
510510
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
511-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
512-
zend_array_destroy(ht);
513-
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
514-
if (EG(exception)) {
515-
ZVAL_UNDEF(EX_VAR(opline->result.var));
516-
} else {
517-
ZVAL_NULL(EX_VAR(opline->result.var));
518-
}
519-
}
520-
return;
521-
}
522-
if (EG(exception)) {
523-
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
524-
ZVAL_UNDEF(EX_VAR(opline->result.var));
525-
}
526-
return;
527-
}
528-
offset_key = ZSTR_EMPTY_ALLOC();
529-
goto str_index;
511+
512+
return;
530513
case IS_DOUBLE:
531514
hval = zend_dval_to_lval(Z_DVAL_P(dim));
532515
if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) {
@@ -667,33 +650,16 @@ static void ZEND_FASTCALL zend_jit_fetch_dim_is_helper(zend_array *ht, zval *dim
667650
}
668651
ZEND_FALLTHROUGH;
669652
case IS_NULL:
670-
/* The array may be destroyed while throwing the notice.
671-
* Temporarily increase the refcount to detect this situation. */
672-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
673-
GC_ADDREF(ht);
653+
retval = zend_hash_find(ht, ZSTR_EMPTY_ALLOC());
654+
if (!retval) {
655+
ZVAL_NULL(result);
656+
} else {
657+
ZVAL_COPY_DEREF(result, retval);
674658
}
675-
execute_data = EG(current_execute_data);
676-
opline = EX(opline);
659+
677660
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
678-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
679-
zend_array_destroy(ht);
680-
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
681-
if (EG(exception)) {
682-
ZVAL_UNDEF(EX_VAR(opline->result.var));
683-
} else {
684-
ZVAL_NULL(EX_VAR(opline->result.var));
685-
}
686-
}
687-
return;
688-
}
689-
if (EG(exception)) {
690-
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
691-
ZVAL_UNDEF(EX_VAR(opline->result.var));
692-
}
693-
return;
694-
}
695-
offset_key = ZSTR_EMPTY_ALLOC();
696-
goto str_index;
661+
662+
return;
697663
case IS_DOUBLE:
698664
hval = zend_dval_to_lval(Z_DVAL_P(dim));
699665
if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) {
@@ -819,22 +785,17 @@ static int ZEND_FASTCALL zend_jit_fetch_dim_isset_helper(zend_array *ht, zval *d
819785
return 0;
820786
}
821787
ZEND_FALLTHROUGH;
822-
case IS_NULL:
823-
/* The array may be destroyed while throwing the notice.
824-
* Temporarily increase the refcount to detect this situation. */
825-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
826-
GC_ADDREF(ht);
788+
case IS_NULL: {
789+
int result = 0;
790+
retval = zend_hash_find(ht, ZSTR_EMPTY_ALLOC());
791+
if (retval) {
792+
result = Z_TYPE_P(retval) > IS_NULL;
827793
}
794+
828795
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
829-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
830-
zend_array_destroy(ht);
831-
return 0;
832-
}
833-
if (EG(exception)) {
834-
return 0;
835-
}
836-
offset_key = ZSTR_EMPTY_ALLOC();
837-
goto str_index;
796+
797+
return result;
798+
}
838799
case IS_DOUBLE:
839800
hval = zend_dval_to_lval(Z_DVAL_P(dim));
840801
if (!zend_is_long_compatible(Z_DVAL_P(dim), hval)) {
@@ -943,13 +904,11 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di
943904
case IS_NULL:
944905
/* The array may be destroyed while throwing the notice.
945906
* Temporarily increase the refcount to detect this situation. */
946-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
947-
GC_ADDREF(ht);
948-
}
907+
GC_TRY_ADDREF(ht);
949908
execute_data = EG(current_execute_data);
950909
opline = EX(opline);
951910
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
952-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
911+
if (GC_DELREF(ht) != 1) {
953912
if (!GC_REFCOUNT(ht)) {
954913
zend_array_destroy(ht);
955914
}
@@ -1103,13 +1062,11 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_w_helper(zend_array *ht, zval *dim
11031062
case IS_NULL:
11041063
/* The array may be destroyed while throwing the notice.
11051064
* Temporarily increase the refcount to detect this situation. */
1106-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
1107-
GC_ADDREF(ht);
1108-
}
1065+
GC_TRY_ADDREF(ht);
11091066
execute_data = EG(current_execute_data);
11101067
opline = EX(opline);
11111068
zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
1112-
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
1069+
if (GC_DELREF(ht) != 1) {
11131070
if (!GC_REFCOUNT(ht)) {
11141071
zend_array_destroy(ht);
11151072
}

0 commit comments

Comments
 (0)