@@ -3935,6 +3935,117 @@ static void preload_link(void)
39353935 } ZEND_HASH_FOREACH_END ();
39363936}
39373937
3938+ #ifdef ZEND_WIN32
3939+ static void preload_check_windows_restriction (zend_class_entry * scope , zend_class_entry * ce ) {
3940+ if (ce && ce -> type == ZEND_INTERNAL_CLASS ) {
3941+ zend_error_noreturn (E_ERROR ,
3942+ "Class %s uses internal class %s during preloading, which is not supported on Windows" ,
3943+ ZSTR_VAL (scope -> name ), ZSTR_VAL (ce -> name ));
3944+ }
3945+ }
3946+
3947+ static void preload_check_windows_restrictions (zend_class_entry * scope ) {
3948+ uint32_t i ;
3949+
3950+ preload_check_windows_restriction (scope , scope -> parent );
3951+
3952+ for (i = 0 ; i < scope -> num_interfaces ; i ++ ) {
3953+ preload_check_windows_restriction (scope , scope -> interfaces [i ]);
3954+ }
3955+ }
3956+ #endif
3957+
3958+ static zend_class_entry * preload_load_prop_type (zend_property_info * prop , zend_string * name ) {
3959+ zend_class_entry * ce ;
3960+ if (zend_string_equals_literal_ci (name , "self" )) {
3961+ ce = prop -> ce ;
3962+ } else if (zend_string_equals_literal_ci (name , "parent" )) {
3963+ ce = prop -> ce -> parent ;
3964+ } else {
3965+ ce = zend_lookup_class (name );
3966+ }
3967+ if (ce ) {
3968+ return ce ;
3969+ }
3970+
3971+ zend_error_noreturn (E_ERROR ,
3972+ "Failed to load class %s used by typed property %s::$%s during preloading" ,
3973+ ZSTR_VAL (name ), ZSTR_VAL (prop -> ce -> name ), zend_get_unmangled_property_name (prop -> name ));
3974+ return ce ;
3975+ }
3976+
3977+ static void preload_ensure_classes_loadable () {
3978+ /* Run this in a loop, because additional classes may be loaded while updating constants etc. */
3979+ uint32_t checked_classes_idx = 0 ;
3980+ while (1 ) {
3981+ zend_class_entry * ce ;
3982+ uint32_t num_classes = zend_hash_num_elements (EG (class_table ));
3983+ if (num_classes == checked_classes_idx ) {
3984+ return ;
3985+ }
3986+
3987+ ZEND_HASH_REVERSE_FOREACH_PTR (EG (class_table ), ce ) {
3988+ if (ce -> type == ZEND_INTERNAL_CLASS || _idx == checked_classes_idx ) {
3989+ break ;
3990+ }
3991+
3992+ if (!(ce -> ce_flags & ZEND_ACC_LINKED )) {
3993+ /* Only require that already linked classes are loadable, we'll properly check
3994+ * things when linking additional classes. */
3995+ continue ;
3996+ }
3997+
3998+ #ifdef ZEND_WIN32
3999+ preload_check_windows_restrictions (ce );
4000+ #endif
4001+
4002+ if (!(ce -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED )) {
4003+ int result = SUCCESS ;
4004+ zend_try {
4005+ result = zend_update_class_constants (ce );
4006+ } zend_catch {
4007+ /* Provide some context for the generated error. */
4008+ zend_error_noreturn (E_ERROR ,
4009+ "Error generated while resolving initializers of class %s during preloading" ,
4010+ ZSTR_VAL (ce -> name ));
4011+ } zend_end_try ();
4012+ if (result == FAILURE ) {
4013+ /* Just present to be safe: We generally always throw some
4014+ * other fatal error as part of update_class_constants(). */
4015+ zend_error_noreturn (E_ERROR ,
4016+ "Failed to resolve initializers of class %s during preloading" ,
4017+ ZSTR_VAL (ce -> name ));
4018+ }
4019+ ZEND_ASSERT (ce -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED );
4020+ }
4021+
4022+ if (!(ce -> ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED )) {
4023+ if (ce -> ce_flags & ZEND_ACC_HAS_TYPE_HINTS ) {
4024+ zend_property_info * prop ;
4025+ ZEND_HASH_FOREACH_PTR (& ce -> properties_info , prop ) {
4026+ if (ZEND_TYPE_HAS_LIST (prop -> type )) {
4027+ void * * entry ;
4028+ ZEND_TYPE_LIST_FOREACH_PTR (ZEND_TYPE_LIST (prop -> type ), entry ) {
4029+ if (ZEND_TYPE_LIST_IS_NAME (* entry )) {
4030+ zend_class_entry * ce = preload_load_prop_type (
4031+ prop , ZEND_TYPE_LIST_GET_NAME (* entry ));
4032+ * entry = ZEND_TYPE_LIST_ENCODE_CE (ce );
4033+ }
4034+ } ZEND_TYPE_LIST_FOREACH_END ();
4035+ } else if (ZEND_TYPE_HAS_NAME (prop -> type )) {
4036+ zend_class_entry * ce =
4037+ preload_load_prop_type (prop , ZEND_TYPE_NAME (prop -> type ));
4038+ ZEND_TYPE_SET_CE (prop -> type , ce );
4039+ }
4040+ } ZEND_HASH_FOREACH_END ();
4041+ }
4042+ ce -> ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED ;
4043+ }
4044+ } ZEND_HASH_FOREACH_END ();
4045+ checked_classes_idx = num_classes ;
4046+ }
4047+ }
4048+
39384049static zend_string * preload_resolve_path (zend_string * filename )
39394050{
39404051 if (is_stream_path (ZSTR_VAL (filename ))) {
@@ -4290,6 +4401,10 @@ static int accel_preload(const char *config)
42904401 CG (unclean_shutdown ) = 1 ;
42914402 ret = FAILURE ;
42924403 }
4404+
4405+ if (ret == SUCCESS ) {
4406+ preload_ensure_classes_loadable ();
4407+ }
42934408 } zend_catch {
42944409 ret = FAILURE ;
42954410 } zend_end_try ();
0 commit comments