Skip to content

Commit 28b03f9

Browse files
committed
Another fix for bug #63217
1 parent 57af94c commit 28b03f9

File tree

8 files changed

+383
-39
lines changed

8 files changed

+383
-39
lines changed

NEWS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ PHP NEWS
1515
. Added syslog.facility and syslog.ident INI entries for customizing syslog
1616
logging. (Philip Prindeville)
1717
. Fixed bug #63217 (Constant numeric strings become integers when used as
18-
ArrayAccess offset). (Rudi Theunissen)
18+
ArrayAccess offset). (Rudi Theunissen, Dmitry)
1919

2020
- DOM:
2121
. Fixed bug #76285 (DOMDocument::formatOutput attribute sometimes ignored).

Zend/zend_compile.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2431,6 +2431,26 @@ static inline void zend_handle_numeric_op(znode *node) /* {{{ */
24312431
}
24322432
/* }}} */
24332433

2434+
static inline void zend_handle_numeric_dim(zend_op *opline, znode *dim_node) /* {{{ */
2435+
{
2436+
if (Z_TYPE(dim_node->u.constant) == IS_STRING) {
2437+
zend_ulong index;
2438+
2439+
if (ZEND_HANDLE_NUMERIC(Z_STR(dim_node->u.constant), index)) {
2440+
/* For numeric indexs we also keep the original value to use by ArrayAccess
2441+
* See bug #63217
2442+
*/
2443+
int c = zend_add_literal(CG(active_op_array), &dim_node->u.constant);
2444+
ZEND_ASSERT(opline->op2.constant + 1 == c);
2445+
ZVAL_LONG(CT_CONSTANT(opline->op2), index);
2446+
Z_EXTRA_P(CT_CONSTANT(opline->op2)) = ZEND_EXTRA_VALUE;
2447+
return;
2448+
}
2449+
}
2450+
Z_EXTRA_P(CT_CONSTANT(opline->op2)) = 0;
2451+
}
2452+
/* }}} */
2453+
24342454
static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node) /* {{{ */
24352455
{
24362456
if (class_node->op_type == IS_CONST) {
@@ -2672,11 +2692,14 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t
26722692
dim_node.op_type = IS_UNUSED;
26732693
} else {
26742694
zend_compile_expr(&dim_node, dim_ast);
2675-
zend_handle_numeric_op(&dim_node);
26762695
}
26772696

26782697
opline = zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node);
26792698
zend_adjust_for_fetch_type(opline, result, type);
2699+
2700+
if (dim_node.op_type == IS_CONST) {
2701+
zend_handle_numeric_dim(opline, &dim_node);
2702+
}
26802703
return opline;
26812704
}
26822705
/* }}} */
@@ -2816,6 +2839,7 @@ static void zend_compile_list_assign(
28162839
zend_ast *elem_ast = list->child[i];
28172840
zend_ast *var_ast, *key_ast;
28182841
znode fetch_result, dim_node;
2842+
zend_op *opline;
28192843

28202844
if (elem_ast == NULL) {
28212845
if (is_keyed) {
@@ -2853,9 +2877,13 @@ static void zend_compile_list_assign(
28532877

28542878
zend_verify_list_assign_target(var_ast, old_style);
28552879

2856-
zend_emit_op(&fetch_result,
2880+
opline = zend_emit_op(&fetch_result,
28572881
elem_ast->attr ? ZEND_FETCH_LIST_W : ZEND_FETCH_LIST_R, expr_node, &dim_node);
28582882

2883+
if (dim_node.op_type == IS_CONST) {
2884+
zend_handle_numeric_dim(opline, &dim_node);
2885+
}
2886+
28592887
if (var_ast->kind == ZEND_AST_ARRAY) {
28602888
if (elem_ast->attr) {
28612889
zend_emit_op(&fetch_result, ZEND_MAKE_REF, &fetch_result, NULL);

Zend/zend_compile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,8 @@ struct _zend_execute_data {
678678
#define IS_VAR (1<<2)
679679
#define IS_CV (1<<3) /* Compiled variable */
680680

681+
#define ZEND_EXTRA_VALUE 1
682+
681683
#include "zend_globals.h"
682684

683685
BEGIN_EXTERN_C()

Zend/zend_execute.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,6 +1878,9 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
18781878
zend_use_object_as_array();
18791879
ZVAL_ERROR(result);
18801880
} else {
1881+
if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
1882+
dim++;
1883+
}
18811884
retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
18821885

18831886
if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
@@ -2035,6 +2038,9 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
20352038
zend_use_object_as_array();
20362039
ZVAL_NULL(result);
20372040
} else {
2041+
if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
2042+
dim++;
2043+
}
20382044
retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
20392045

20402046
ZEND_ASSERT(result != NULL);
@@ -2077,16 +2083,16 @@ static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_read_IS
20772083
zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0 EXECUTE_DATA_CC);
20782084
}
20792085

2080-
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_LIST_w(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
2086+
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_LIST_w(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
20812087
{
20822088
zval *result = EX_VAR(opline->result.var);
2083-
zend_fetch_dimension_address(result, container, dim, IS_TMP_VAR, BP_VAR_W EXECUTE_DATA_CC);
2089+
zend_fetch_dimension_address(result, container, dim, dim_type, BP_VAR_W EXECUTE_DATA_CC);
20842090
}
20852091

2086-
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_LIST_r(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
2092+
static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_LIST_r(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
20872093
{
20882094
zval *result = EX_VAR(opline->result.var);
2089-
zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, BP_VAR_R, 0, 0 EXECUTE_DATA_CC);
2095+
zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 0, 0 EXECUTE_DATA_CC);
20902096
}
20912097

20922098
ZEND_API void zend_fetch_dimension_const(zval *result, zval *container, zval *dim, int type)

Zend/zend_vm_def.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,9 @@ ZEND_VM_C_LABEL(assign_dim_op_convert_to_array):
907907

908908
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
909909
value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
910+
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
911+
dim++;
912+
}
910913
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op EXECUTE_DATA_CC);
911914
} else {
912915
if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
@@ -1644,6 +1647,9 @@ ZEND_VM_C_LABEL(fetch_dim_r_array):
16441647
}
16451648
} else {
16461649
ZEND_VM_C_LABEL(fetch_dim_r_slow):
1650+
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
1651+
dim++;
1652+
}
16471653
zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
16481654
}
16491655
} else {
@@ -2048,7 +2054,7 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV)
20482054

20492055
SAVE_OPLINE();
20502056
container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
2051-
zend_fetch_dimension_address_LIST_r(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R) OPLINE_CC EXECUTE_DATA_CC);
2057+
zend_fetch_dimension_address_LIST_r(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
20522058
FREE_OP2();
20532059
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
20542060
}
@@ -2068,9 +2074,9 @@ ZEND_VM_HANDLER(198, ZEND_FETCH_LIST_W, VAR|CV, CONST|TMPVAR|CV)
20682074
&& UNEXPECTED(!Z_ISREF_P(container))
20692075
) {
20702076
zend_error(E_NOTICE, "Attempting to set reference to non referenceable value");
2071-
zend_fetch_dimension_address_LIST_r(container, dim OPLINE_CC EXECUTE_DATA_CC);
2077+
zend_fetch_dimension_address_LIST_r(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
20722078
} else {
2073-
zend_fetch_dimension_address_LIST_w(container, dim OPLINE_CC EXECUTE_DATA_CC);
2079+
zend_fetch_dimension_address_LIST_w(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
20742080
}
20752081

20762082
FREE_OP2();
@@ -2247,6 +2253,9 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
22472253
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
22482254
value = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);
22492255

2256+
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
2257+
dim++;
2258+
}
22502259
zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC);
22512260

22522261
FREE_OP_DATA();
@@ -5595,6 +5604,9 @@ ZEND_VM_C_LABEL(num_index_dim):
55955604
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
55965605
zend_use_object_as_array();
55975606
} else {
5607+
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
5608+
offset++;
5609+
}
55985610
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
55995611
}
56005612
} else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
@@ -6318,6 +6330,9 @@ ZEND_VM_C_LABEL(num_index_prop):
63186330
}
63196331
}
63206332

6333+
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
6334+
offset++;
6335+
}
63216336
if (!(opline->extended_value & ZEND_ISEMPTY)) {
63226337
result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC);
63236338
} else {
@@ -8684,6 +8699,9 @@ ZEND_VM_C_LABEL(fetch_dim_r_index_array):
86848699
} else {
86858700
ZEND_VM_C_LABEL(fetch_dim_r_index_slow):
86868701
SAVE_OPLINE();
8702+
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
8703+
dim++;
8704+
}
86878705
zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
86888706
FREE_OP1();
86898707
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();

0 commit comments

Comments
 (0)