]> granicus.if.org Git - php/commitdiff
Partial fix that allows internal constructors to set $this to null.
authorDmitry Stogov <dmitry@zend.com>
Wed, 9 Jul 2014 07:57:42 +0000 (11:57 +0400)
committerDmitry Stogov <dmitry@zend.com>
Wed, 9 Jul 2014 07:57:42 +0000 (11:57 +0400)
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().

13 files changed:
Zend/zend_API.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/date/php_date.c
ext/fileinfo/fileinfo.c
ext/intl/breakiterator/rulebasedbreakiterator_methods.cpp
ext/intl/calendar/gregoriancalendar_methods.cpp
ext/intl/collator/collator_create.c
ext/intl/dateformat/dateformat_create.cpp
ext/intl/formatter/formatter_main.c
ext/intl/msgformat/msgformat.c
ext/intl/resourcebundle/resourcebundle_class.c
ext/pdo/pdo_dbh.c

index b702bd41384dd0a250c1aaae2b148e97f15588a2..beca63c50b4b2055676948c664d201c071b4f43d 100644 (file)
@@ -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)))
index 8ca796810992985ef1d7977cd6e7e6daadcf4f0e..1ac9f63570bb6a3b9bdff751959c4644777ed5ff 100644 (file)
@@ -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();
index 797c4e0943e03e3054e71dbe394296ee54e79ae8..9e06d76d47a31b76069266a39311999252422fb5 100644 (file)
@@ -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();
 }
index a87cfa60f9a76d1aeaf159edd3fe1858f0023802..758d0f9513c51d4dc7e2a816d1bd2c8431603ef6 100644 (file)
@@ -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);
index 86cd02a613943e35d6b70643b91d58414fe32c5a..a612e0428034b1ac4b3f83194a25accb17bc2b22 100644 (file)
@@ -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)
 
index e171cf76abcb403ab1c9ccd21e219ffc5721b00d..50df1a61aba1cc6339b1fb6e1877d7bbe2cf3604 100644 (file)
@@ -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();
        }
 }
 
index 41e2735485be64b226c54a614f7ee2837622d545..e62164f7d661b872f728f017ec5c7e85091181a0 100644 (file)
@@ -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();
        }
 }
 
index 7ed4c534394b48fdebe25873d47c90dc57bf9b99..5801a68d0d27cbdc22f2a40a8dbc6153395f1189 100644 (file)
@@ -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();
+       }
 }
 /* }}} */
 
index f678f5f54e769417659af3fea175a30b17fdb93d..856db16b1d8d612492079fcbd178f6b3642a30d0 100644 (file)
@@ -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();
+       }
 }
 /* }}} */
index 233e0e285b05c1e4be7d2ebdc6c706112f16e812..26473ebe786acd2edb00881515912e2ee7352705 100644 (file)
@@ -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();
+       }
 }
 /* }}} */
 
index 62999436c210c1389a347900ccc52f45433ac527..b9f6c7a369e8ff0bfba3d169fca07e19a6feaf6c 100644 (file)
@@ -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();
+       }
 }
 /* }}} */
 
index 8d6ce87ac85d28c5a4834af4cd3d771a562ae91c..77f2e90588adfe3026506226c9c570dd674cded7 100644 (file)
@@ -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();
+       }
 }
 /* }}} */
 
index f8f4f7960264a7b15c4b3f58a032fa089128a843..b2904118e8ed99d61f1e800264c30a539069415a 100644 (file)
@@ -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);