From: Dmitry Stogov Date: Wed, 18 Mar 2009 13:11:32 +0000 (+0000) Subject: Fixed bug #47704 (PHP crashes on some "bad" operations with string offsets) X-Git-Tag: php-5.2.10RC1~283 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9e48089f65b762d7ac902a6269418ba3cad0c0ba;p=php Fixed bug #47704 (PHP crashes on some "bad" operations with string offsets) --- diff --git a/NEWS b/NEWS index 20c212683f..80f6254021 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS - Fixed memory corruptions while reading properties of zip files. (Ilia) +- Fixed bug #47704 (PHP crashes on some "bad" operations with string offsets). + (Dmitry) - Fixed bug #47667 (ZipArchive::OVERWRITE seems to have no effect). (Mikko, Pierre) - Fixed bug #47644 (Valid integers are truncated with json_decode()). (Scott) - Fixed bug #47639 (pg_copy_from() WARNING: nonstandard use of \\ in a string diff --git a/Zend/tests/bug47704.phpt b/Zend/tests/bug47704.phpt new file mode 100644 index 0000000000..151754a4f9 --- /dev/null +++ b/Zend/tests/bug47704.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bug #47704 (crashes on some "bad" operations with string offsets) +--FILE-- +a += 1; +?> +--EXPECTF-- +Fatal error: Cannot use string offset as an object in %sbug47704.php on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 54064509c3..e00b417659 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -294,6 +294,10 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (OP1_TYPE == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -545,6 +549,10 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR| zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (OP1_TYPE == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -637,6 +645,10 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (OP1_TYPE == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 50176ad13a..8a7d89917b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -8553,6 +8553,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -8803,6 +8807,10 @@ static int zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZE zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -8895,6 +8903,10 @@ static int zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, Z zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -10070,6 +10082,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*binary_op)(zval * zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -10321,6 +10337,10 @@ static int zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t incdec_op, ZEND zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -10413,6 +10433,10 @@ static int zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t incdec_op, ZEN zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -11591,6 +11615,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*binary_op)(zval * zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -11842,6 +11870,10 @@ static int zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t incdec_op, ZEND zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -11934,6 +11966,10 @@ static int zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t incdec_op, ZEN zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -12926,6 +12962,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zva zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -13607,6 +13647,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*binary_op)(zval *r zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -13857,6 +13901,10 @@ static int zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op, ZEND_ zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -13949,6 +13997,10 @@ static int zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op, ZEND zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_VAR == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -15017,6 +15069,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(z zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -15266,6 +15322,10 @@ static int zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -15358,6 +15418,10 @@ static int zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -16041,6 +16105,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zva zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -16291,6 +16359,10 @@ static int zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_t incdec_op, Z zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -16383,6 +16455,10 @@ static int zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec_t incdec_op, zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -17022,6 +17098,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zva zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -17272,6 +17352,10 @@ static int zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_t incdec_op, Z zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -17364,6 +17448,10 @@ static int zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec_t incdec_op, zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -18003,6 +18091,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)( zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -18269,6 +18361,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -18518,6 +18614,10 @@ static int zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op, ZE zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -18610,6 +18710,10 @@ static int zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op, Z zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_UNUSED == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -20711,6 +20815,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -20960,6 +21068,10 @@ static int zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEN zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -21052,6 +21164,10 @@ static int zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZE zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -22220,6 +22336,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*binary_op)(zval *r zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -22470,6 +22590,10 @@ static int zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t incdec_op, ZEND_ zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -22562,6 +22686,10 @@ static int zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t incdec_op, ZEND zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -23733,6 +23861,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*binary_op)(zval *r zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -23983,6 +24115,10 @@ static int zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t incdec_op, ZEND_ zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -24075,6 +24211,10 @@ static int zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t incdec_op, ZEND zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -25059,6 +25199,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -25739,6 +25883,10 @@ static int zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *re zval **retval = &EX_T(result->u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + EX_T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -25988,6 +26136,10 @@ static int zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_O zval **retval = &EX_T(opline->result.u.var).var.ptr; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -26080,6 +26232,10 @@ static int zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_ zval *retval = &EX_T(opline->result.u.var).tmp_var; int have_get_ptr = 0; + if (IS_CV == IS_VAR && !object_ptr) { + zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr;