]> granicus.if.org Git - php/commitdiff
Properly handle property read on const/tmp
authorNikita Popov <nikic@php.net>
Sat, 31 May 2014 15:51:22 +0000 (17:51 +0200)
committerNikita Popov <nikic@php.net>
Sat, 31 May 2014 15:51:22 +0000 (17:51 +0200)
Zend/tests/varSyntax/parenthesesDeref.phpt [new file with mode: 0644]
Zend/tests/varSyntax/propertyOfStringError.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/varSyntax/parenthesesDeref.phpt b/Zend/tests/varSyntax/parenthesesDeref.phpt
new file mode 100644 (file)
index 0000000..0ebfe9c
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Dereferencing expression parentheses
+--FILE--
+<?php
+
+$array = [&$array, 1];
+var_dump(($array)[1]);
+var_dump((($array[0][0])[0])[1]);
+
+var_dump(((object) ['a' => 0, 'b' => 1])->b);
+
+$obj = (object) ['a' => 0, 'b' => ['var_dump', 1]];
+(clone $obj)->b[0](1);
+
+?>
+--EXPECT--
+int(1)
+int(1)
+int(1)
+int(1)
diff --git a/Zend/tests/varSyntax/propertyOfStringError.phpt b/Zend/tests/varSyntax/propertyOfStringError.phpt
new file mode 100644 (file)
index 0000000..85abc58
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+Cannot take property of a string
+--FILE--
+<?php
+
+"foo"->bar;
+
+?>
+--EXPECTF--
+Notice: Trying to get property of non-object in %s on line %d
index 2bd02809007218948b0e33980ff218b0ef70cdb9..aaf1e494bb4ea382673a1b60a468d7883fbb4670 100644 (file)
@@ -1386,7 +1386,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV)
        ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HELPER(zend_fetch_property_address_read_helper, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
 {
        USE_OPLINE
        zend_free_op free_op1;
@@ -1419,7 +1419,7 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP
        ZEND_VM_NEXT_OPCODE();
 }
 
-ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
 {
        ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper);
 }
index 24f016066cbec9a4e483576632df635aa864fcc4..d2b8f57d797224d5fcf5fa78a0e3a027a0824223 100644 (file)
@@ -3725,6 +3725,43 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       zval *container;
+
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = opline->op1.zv;
+       offset  = opline->op2.zv;
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -4704,6 +4741,44 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HA
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       zval *container;
+       zend_free_op free_op2;
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = opline->op1.zv;
+       offset  = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+       zval_dtor(free_op2.var);
+
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -5532,6 +5607,44 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HA
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       zval *container;
+       zend_free_op free_op2;
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = opline->op1.zv;
+       offset  = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+       zval_ptr_dtor_nogc(free_op2.var);
+
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -7039,6 +7152,43 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAN
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+
+       zval *container;
+
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = opline->op1.zv;
+       offset  = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -8896,6 +9046,43 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HA
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_free_op free_op1;
+       zval *container;
+
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+       offset  = opline->op2.zv;
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+       zval_dtor(free_op1.var);
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -9743,6 +9930,44 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAND
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_free_op free_op1;
+       zval *container;
+       zend_free_op free_op2;
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+       offset  = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+       zval_dtor(free_op2.var);
+       zval_dtor(free_op1.var);
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -10571,6 +10796,44 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_free_op free_op1;
+       zval *container;
+       zend_free_op free_op2;
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+       offset  = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+       zval_ptr_dtor_nogc(free_op2.var);
+       zval_dtor(free_op1.var);
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -11946,6 +12209,43 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDL
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS)
+{
+       USE_OPLINE
+       zend_free_op free_op1;
+       zval *container;
+
+       zval *offset;
+
+       SAVE_OPLINE();
+       container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
+       offset  = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
+
+       if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) ||
+           UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
+               zend_error(E_NOTICE, "Trying to get property of non-object");
+               ZVAL_NULL(EX_VAR(opline->result.var));
+       } else {
+               zval *retval;
+
+               /* here we are sure we are dealing with an object */
+               retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC);
+
+               if (retval != EX_VAR(opline->result.var)) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), retval);
+               }
+       }
+
+       zval_dtor(free_op1.var);
+       CHECK_EXCEPTION();
+       ZEND_VM_NEXT_OPCODE();
+}
+
+static int ZEND_FASTCALL  ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+}
+
 static int ZEND_FASTCALL  ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -41965,16 +42265,16 @@ void zend_init_opcodes_handlers(void)
        ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER,
        ZEND_NULL_HANDLER,
        ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER,
        ZEND_NULL_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER,
        ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
+       ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER,
        ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER,
        ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER,
        ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER,