mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
Partial fix that allows internal constructors to set $this to null.
The address of $this passed to drectly called internal constructor in execute_data->return_value. Internal constructors should use ZEND_CTOR_MAKE_NULL() macro (insted of previous ZEND_NULL(EG(This))) to do the work. This patch doesn't fix the problem for indirectly called constructors. e.g. parant::__construct().
This commit is contained in:
parent
ca414c6904
commit
1dd07d6bf4
@ -637,6 +637,27 @@ END_EXTERN_C()
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* May be used in internal constructors to make them return NULL */
|
||||
#if 1 // support for directly called constructors only ???
|
||||
#define ZEND_CTOR_MAKE_NULL() do { \
|
||||
if (EG(current_execute_data)->return_value) { \
|
||||
zval_ptr_dtor(EG(current_execute_data)->return_value); \
|
||||
ZVAL_NULL(EG(current_execute_data)->return_value); \
|
||||
} \
|
||||
} while (0)
|
||||
#else // attempt to support calls to parent::__construct() ???
|
||||
#define ZEND_CTOR_MAKE_NULL() do { \
|
||||
if (EG(current_execute_data)->return_value) { \
|
||||
zval_ptr_dtor(EG(current_execute_data)->return_value); \
|
||||
ZVAL_NULL(EG(current_execute_data)->return_value); \
|
||||
} else if (EG(current_execute_data)->prev_execute_data && \
|
||||
EG(current_execute_data)->prev_execute_data->object == \
|
||||
EG(current_execute_data)->object) { \
|
||||
EG(current_execute_data)->prev_execute_data->object = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; }
|
||||
|
||||
#define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties((p) TSRMLS_CC) : NULL)))
|
||||
|
@ -2363,6 +2363,10 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
|
||||
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (OP2_TYPE == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
@ -3490,6 +3494,9 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
|
||||
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
|
||||
EX(call)->return_value = EX_VAR(opline->result.var);
|
||||
} else {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
|
@ -982,6 +982,9 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
|
||||
EX(call)->return_value = EX_VAR(opline->result.var);
|
||||
} else {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
@ -3808,6 +3811,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_CONST == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -4774,6 +4781,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_TMP_VAR == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -5608,6 +5619,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_VAR == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -6301,6 +6316,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_UNUSED == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -7130,6 +7149,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_CV == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -15438,6 +15461,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_CONST == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -17666,6 +17693,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_TMP_VAR == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -19861,6 +19892,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_VAR == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -21325,6 +21360,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_UNUSED == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -23228,6 +23267,10 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
|
||||
EX(call) = zend_vm_stack_push_call_frame(
|
||||
fbc, opline->extended_value, 0, ce, object, EX(call) TSRMLS_CC);
|
||||
|
||||
if (IS_CV == IS_UNUSED) {
|
||||
EX(call)->return_value = NULL;
|
||||
}
|
||||
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
@ -2683,7 +2683,7 @@ PHP_METHOD(DateTime, __construct)
|
||||
zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
|
||||
if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone)) {
|
||||
if (!php_date_initialize(Z_PHPDATE_P(getThis()), time_str, time_str_len, NULL, timezone_object, 1 TSRMLS_CC)) {
|
||||
//??? ZVAL_NULL(getThis());
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
zend_restore_error_handling(&error_handling TSRMLS_CC);
|
||||
|
@ -287,6 +287,7 @@ PHP_MINFO_FUNCTION(fileinfo)
|
||||
if (object) { \
|
||||
zend_object_store_ctor_failed(Z_OBJ_P(object) TSRMLS_CC); \
|
||||
Z_OBJ_P(object) = NULL; \
|
||||
ZEND_CTOR_MAKE_NULL(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -105,6 +105,7 @@ U_CFUNC PHP_METHOD(IntlRuleBasedBreakIterator, __construct)
|
||||
if (Z_TYPE_P(return_value) == IS_OBJECT && Z_OBJ_P(return_value) == NULL) {
|
||||
zend_object_store_ctor_failed(Z_OBJ(orig_this) TSRMLS_CC);
|
||||
zval_dtor(&orig_this);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,6 +198,8 @@ U_CFUNC PHP_METHOD(IntlGregorianCalendar, __construct)
|
||||
|
||||
if (Z_TYPE_P(return_value) == IS_OBJECT && Z_OBJ_P(return_value) == NULL) {
|
||||
zend_object_store_ctor_failed(Z_OBJ(orig_this) TSRMLS_CC);
|
||||
zval_dtor(&orig_this);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,8 +72,16 @@ PHP_FUNCTION( collator_create )
|
||||
*/
|
||||
PHP_METHOD( Collator, __construct )
|
||||
{
|
||||
zval orig_this = *getThis();
|
||||
|
||||
return_value = getThis();
|
||||
collator_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
|
||||
if (Z_TYPE_P(return_value) == IS_OBJECT && Z_OBJ_P(return_value) == NULL) {
|
||||
zend_object_store_ctor_failed(Z_OBJ(orig_this) TSRMLS_CC);
|
||||
zval_dtor(&orig_this);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -187,9 +187,17 @@ U_CFUNC PHP_FUNCTION( datefmt_create )
|
||||
*/
|
||||
U_CFUNC PHP_METHOD( IntlDateFormatter, __construct )
|
||||
{
|
||||
zval orig_this = *getThis();
|
||||
|
||||
/* return_value param is being changed, therefore we will always return
|
||||
* NULL here */
|
||||
return_value = getThis();
|
||||
datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
|
||||
if (Z_TYPE_P(return_value) == IS_OBJECT && Z_OBJ_P(return_value) == NULL) {
|
||||
zend_object_store_ctor_failed(Z_OBJ(orig_this) TSRMLS_CC);
|
||||
zval_dtor(&orig_this);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -90,8 +90,16 @@ PHP_FUNCTION( numfmt_create )
|
||||
*/
|
||||
PHP_METHOD( NumberFormatter, __construct )
|
||||
{
|
||||
zval orig_this = *getThis();
|
||||
|
||||
return_value = getThis();
|
||||
numfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
|
||||
if (Z_TYPE_P(return_value) == IS_OBJECT && Z_OBJ_P(return_value) == NULL) {
|
||||
zend_object_store_ctor_failed(Z_OBJ(orig_this) TSRMLS_CC);
|
||||
zval_dtor(&orig_this);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -108,8 +108,16 @@ PHP_FUNCTION( msgfmt_create )
|
||||
*/
|
||||
PHP_METHOD( MessageFormatter, __construct )
|
||||
{
|
||||
zval orig_this = *getThis();
|
||||
|
||||
return_value = getThis();
|
||||
msgfmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
|
||||
if (Z_TYPE_P(return_value) == IS_OBJECT && Z_OBJ_P(return_value) == NULL) {
|
||||
zend_object_store_ctor_failed(Z_OBJ(orig_this) TSRMLS_CC);
|
||||
zval_dtor(&orig_this);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -139,8 +139,16 @@ ZEND_END_ARG_INFO()
|
||||
*/
|
||||
PHP_METHOD( ResourceBundle, __construct )
|
||||
{
|
||||
zval orig_this = *getThis();
|
||||
|
||||
return_value = getThis();
|
||||
resourcebundle_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
|
||||
if (Z_TYPE_P(return_value) == IS_OBJECT && Z_OBJ_P(return_value) == NULL) {
|
||||
zend_object_store_ctor_failed(Z_OBJ(orig_this) TSRMLS_CC);
|
||||
zval_dtor(&orig_this);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -211,7 +211,7 @@ static PHP_METHOD(PDO, dbh_constructor)
|
||||
|
||||
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!s!a!", &data_source, &data_source_len,
|
||||
&username, &usernamelen, &password, &passwordlen, &options)) {
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ static PHP_METHOD(PDO, dbh_constructor)
|
||||
snprintf(alt_dsn, sizeof(alt_dsn), "pdo.dsn.%s", data_source);
|
||||
if (FAILURE == cfg_get_string(alt_dsn, &ini_dsn)) {
|
||||
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source name");
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ static PHP_METHOD(PDO, dbh_constructor)
|
||||
|
||||
if (!colon) {
|
||||
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source name (via INI: %s)", alt_dsn);
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -244,13 +244,13 @@ static PHP_METHOD(PDO, dbh_constructor)
|
||||
data_source = dsn_from_uri(data_source + sizeof("uri:")-1, alt_dsn, sizeof(alt_dsn) TSRMLS_CC);
|
||||
if (!data_source) {
|
||||
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source URI");
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
colon = strchr(data_source, ':');
|
||||
if (!colon) {
|
||||
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "invalid data source name (via URI)");
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -261,7 +261,7 @@ static PHP_METHOD(PDO, dbh_constructor)
|
||||
/* NB: don't want to include the data_source in the error message as
|
||||
* it might contain a password */
|
||||
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, "could not find driver");
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -401,7 +401,7 @@ options:
|
||||
|
||||
/* the connection failed; things will tidy up in free_storage */
|
||||
/* XXX raise exception */
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -461,6 +461,7 @@ static void pdo_stmt_construct(pdo_stmt_t *stmt, zval *object, zend_class_entry
|
||||
|
||||
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
|
||||
Z_OBJ_P(object) = NULL;
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
object = NULL; /* marks failure */
|
||||
} else if (!Z_ISUNDEF(retval)) {
|
||||
zval_ptr_dtor(&retval);
|
||||
|
Loading…
Reference in New Issue
Block a user