@@ -3296,6 +3296,106 @@ static void get_unresolved_initializer(zend_class_entry *ce, const char **kind,
3296
3296
} ZEND_HASH_FOREACH_END ();
3297
3297
}
3298
3298
3299
+ static zend_bool preload_try_resolve_constants (zend_class_entry * ce )
3300
+ {
3301
+ zend_bool ok , changed ;
3302
+ zend_class_constant * c ;
3303
+ zval * val ;
3304
+
3305
+ EG (exception ) = (void * )(uintptr_t )-1 ; /* prevent error reporting */
3306
+ do {
3307
+ ok = 1 ;
3308
+ changed = 0 ;
3309
+ ZEND_HASH_FOREACH_PTR (& ce -> constants_table , c ) {
3310
+ val = & c -> value ;
3311
+ if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
3312
+ if (EXPECTED (zval_update_constant_ex (val , c -> ce ) == SUCCESS )) {
3313
+ changed = 1 ;
3314
+ } else {
3315
+ ok = 0 ;
3316
+ }
3317
+ }
3318
+ } ZEND_HASH_FOREACH_END ();
3319
+ if (ce -> default_properties_count ) {
3320
+ uint32_t i ;
3321
+ for (i = 0 ; i < ce -> default_properties_count ; i ++ ) {
3322
+ val = & ce -> default_properties_table [i ];
3323
+ if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
3324
+ zend_property_info * prop = ce -> properties_info_table [i ];
3325
+ if (UNEXPECTED (zval_update_constant_ex (val , prop -> ce ) != SUCCESS )) {
3326
+ ok = 0 ;
3327
+ }
3328
+ }
3329
+ }
3330
+ }
3331
+ if (ce -> default_static_members_count ) {
3332
+ uint32_t count = ce -> parent ? ce -> default_static_members_count - ce -> parent -> default_static_members_count : ce -> default_static_members_count ;
3333
+
3334
+ val = ce -> default_static_members_table + ce -> default_static_members_count - 1 ;
3335
+ while (count ) {
3336
+ if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
3337
+ if (UNEXPECTED (zval_update_constant_ex (val , ce ) != SUCCESS )) {
3338
+ ok = 0 ;
3339
+ }
3340
+ }
3341
+ val -- ;
3342
+ count -- ;
3343
+ }
3344
+ }
3345
+ } while (changed && !ok );
3346
+ EG (exception ) = NULL ;
3347
+
3348
+ return ok ;
3349
+ }
3350
+
3351
+ static zend_bool preload_try_resolve_property_types (zend_class_entry * ce )
3352
+ {
3353
+ zend_bool ok = 1 ;
3354
+ zend_property_info * prop ;
3355
+ zend_class_entry * p ;
3356
+
3357
+ if (ce -> ce_flags & ZEND_ACC_HAS_TYPE_HINTS ) {
3358
+ ZEND_HASH_FOREACH_PTR (& ce -> properties_info , prop ) {
3359
+ zend_string * name , * lcname ;
3360
+
3361
+ if (!ZEND_TYPE_IS_NAME (prop -> type )) {
3362
+ continue ;
3363
+ }
3364
+
3365
+ name = ZEND_TYPE_NAME (prop -> type );
3366
+ lcname = zend_string_tolower (name );
3367
+ p = zend_hash_find_ptr (EG (class_table ), lcname );
3368
+ zend_string_release (lcname );
3369
+ if (!p ) {
3370
+ ok = 0 ;
3371
+ continue ;
3372
+ }
3373
+ if (p != ce ) {
3374
+ #ifdef ZEND_WIN32
3375
+ /* On Windows we can't link with internal class, because of ASLR */
3376
+ if (p -> type == ZEND_INTERNAL_CLASS ) {
3377
+ ok = 0 ;
3378
+ continue ;
3379
+ }
3380
+ #endif
3381
+ if (!(p -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED )) {
3382
+ ok = 0 ;
3383
+ continue ;
3384
+ }
3385
+ if (!(p -> ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED )) {
3386
+ ok = 0 ;
3387
+ continue ;
3388
+ }
3389
+ }
3390
+
3391
+ zend_string_release (name );
3392
+ prop -> type = ZEND_TYPE_ENCODE_CE (p , ZEND_TYPE_ALLOW_NULL (prop -> type ));
3393
+ } ZEND_HASH_FOREACH_END ();
3394
+ }
3395
+
3396
+ return ok ;
3397
+ }
3398
+
3299
3399
static void preload_link (void )
3300
3400
{
3301
3401
zval * zv ;
@@ -3339,6 +3439,12 @@ static void preload_link(void)
3339
3439
/* On Windows we can't link with internal class, because of ASLR */
3340
3440
if (parent -> type == ZEND_INTERNAL_CLASS ) continue ;
3341
3441
#endif
3442
+ if (!(parent -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED )) {
3443
+ continue ;
3444
+ }
3445
+ if (!(parent -> ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED )) {
3446
+ continue ;
3447
+ }
3342
3448
}
3343
3449
3344
3450
if (ce -> num_interfaces ) {
@@ -3356,6 +3462,10 @@ static void preload_link(void)
3356
3462
break ;
3357
3463
}
3358
3464
#endif
3465
+ if (!(p -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED )) {
3466
+ found = 0 ;
3467
+ break ;
3468
+ }
3359
3469
}
3360
3470
if (!found ) continue ;
3361
3471
}
@@ -3387,111 +3497,42 @@ static void preload_link(void)
3387
3497
/* Set filename & lineno information for inheritance errors */
3388
3498
CG (in_compilation ) = 1 ;
3389
3499
CG (compiled_filename ) = ce -> info .user .filename ;
3390
- CG (zend_lineno ) = ce -> info .user .line_start ;
3500
+ if (ce -> parent_name
3501
+ && !ce -> num_interfaces
3502
+ && !ce -> num_traits
3503
+ && (parent -> type == ZEND_INTERNAL_CLASS
3504
+ || parent -> info .user .filename == ce -> info .user .filename )) {
3505
+ /* simulate early binding */
3506
+ CG (zend_lineno ) = ce -> info .user .line_end ;
3507
+ } else {
3508
+ CG (zend_lineno ) = ce -> info .user .line_start ;
3509
+ }
3391
3510
zend_do_link_class (ce , parent );
3392
3511
CG (in_compilation ) = 0 ;
3393
3512
CG (compiled_filename ) = NULL ;
3394
3513
3395
3514
changed = 1 ;
3396
3515
}
3397
3516
}
3398
- } ZEND_HASH_FOREACH_END ();
3399
- } while (changed );
3400
-
3401
- /* Resolve class constants */
3402
- EG (exception ) = (void * )(uintptr_t )-1 ; /* prevent error reporting */
3403
- do {
3404
- changed = 0 ;
3405
- ZEND_HASH_REVERSE_FOREACH_VAL (EG (class_table ), zv ) {
3406
- ce = Z_PTR_P (zv );
3407
- if (ce -> type == ZEND_INTERNAL_CLASS ) {
3408
- break ;
3409
- }
3410
- if ((ce -> ce_flags & ZEND_ACC_LINKED )
3411
- && !(ce -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED )) {
3412
- zend_bool ok = 1 ;
3413
- zend_class_constant * c ;
3414
- zval * val ;
3415
-
3416
- ZEND_HASH_FOREACH_PTR (& ce -> constants_table , c ) {
3417
- val = & c -> value ;
3418
- if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
3419
- if (EXPECTED (zval_update_constant_ex (val , c -> ce ) == SUCCESS )) {
3420
- changed = 1 ;
3421
- } else {
3422
- ok = 0 ;
3423
- }
3424
- }
3425
- } ZEND_HASH_FOREACH_END ();
3426
- if (ce -> default_properties_count ) {
3427
- uint32_t i ;
3428
- for (i = 0 ; i < ce -> default_properties_count ; i ++ ) {
3429
- val = & ce -> default_properties_table [i ];
3430
- if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
3431
- zend_property_info * prop = ce -> properties_info_table [i ];
3432
- if (UNEXPECTED (zval_update_constant_ex (val , prop -> ce ) != SUCCESS )) {
3433
- ok = 0 ;
3434
- }
3435
- }
3517
+ if (ce -> ce_flags & ZEND_ACC_LINKED ) {
3518
+ if (!(ce -> ce_flags & ZEND_ACC_CONSTANTS_UPDATED )) {
3519
+ if ((ce -> ce_flags & ZEND_ACC_TRAIT ) /* don't update traits */
3520
+ || preload_try_resolve_constants (ce )) {
3521
+ ce -> ce_flags |= ZEND_ACC_CONSTANTS_UPDATED ;
3522
+ changed = 1 ;
3436
3523
}
3437
3524
}
3438
- if (ce -> default_static_members_count ) {
3439
- uint32_t count = ce -> parent ? ce -> default_static_members_count - ce -> parent -> default_static_members_count : ce -> default_static_members_count ;
3440
-
3441
- val = ce -> default_static_members_table + ce -> default_static_members_count - 1 ;
3442
- while (count ) {
3443
- if (Z_TYPE_P (val ) == IS_CONSTANT_AST ) {
3444
- if (UNEXPECTED (zval_update_constant_ex (val , ce ) != SUCCESS )) {
3445
- ok = 0 ;
3446
- }
3447
- }
3448
- val -- ;
3449
- count -- ;
3525
+
3526
+ if (!(ce -> ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED )) {
3527
+ if ((ce -> ce_flags & ZEND_ACC_TRAIT ) /* don't update traits */
3528
+ || preload_try_resolve_property_types (ce )) {
3529
+ ce -> ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED ;
3530
+ changed = 1 ;
3450
3531
}
3451
3532
}
3452
- if (ok ) {
3453
- ce -> ce_flags |= ZEND_ACC_CONSTANTS_UPDATED ;
3454
- }
3455
3533
}
3456
3534
} ZEND_HASH_FOREACH_END ();
3457
3535
} while (changed );
3458
- EG (exception ) = NULL ;
3459
-
3460
- /* Resolve property types */
3461
- ZEND_HASH_REVERSE_FOREACH_VAL (EG (class_table ), zv ) {
3462
- ce = Z_PTR_P (zv );
3463
- if (ce -> type == ZEND_INTERNAL_CLASS ) {
3464
- break ;
3465
- }
3466
- if ((ce -> ce_flags & ZEND_ACC_LINKED )
3467
- && !(ce -> ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED )) {
3468
- zend_bool ok = 1 ;
3469
- zend_property_info * prop ;
3470
- if (ce -> ce_flags & ZEND_ACC_HAS_TYPE_HINTS ) {
3471
- ZEND_HASH_FOREACH_PTR (& ce -> properties_info , prop ) {
3472
- zend_string * name , * lcname ;
3473
- if (!ZEND_TYPE_IS_NAME (prop -> type )) {
3474
- continue ;
3475
- }
3476
-
3477
- name = ZEND_TYPE_NAME (prop -> type );
3478
- lcname = zend_string_tolower (name );
3479
- p = zend_hash_find_ptr (EG (class_table ), lcname );
3480
- zend_string_release (lcname );
3481
- if (!p ) {
3482
- ok = 0 ;
3483
- continue ;
3484
- }
3485
-
3486
- zend_string_release (name );
3487
- prop -> type = ZEND_TYPE_ENCODE_CE (p , ZEND_TYPE_ALLOW_NULL (prop -> type ));
3488
- } ZEND_HASH_FOREACH_END ();
3489
- }
3490
- if (ok ) {
3491
- ce -> ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED ;
3492
- }
3493
- }
3494
- } ZEND_HASH_FOREACH_END ();
3495
3536
3496
3537
/* Move unlinked clases (and with unresilved constants) back to scripts */
3497
3538
orig_dtor = EG (class_table )-> pDestructor ;
0 commit comments