@@ -449,21 +449,57 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T
449
449
zend_bool result ;
450
450
451
451
SAVE_OPLINE ();
452
- op1 = GET_OP1_ZVAL_PTR_DEREF (BP_VAR_R );
453
- op2 = GET_OP2_ZVAL_PTR_DEREF (BP_VAR_R );
452
+ op1 = GET_OP1_ZVAL_PTR_UNDEF (BP_VAR_R );
453
+ op2 = GET_OP2_ZVAL_PTR_UNDEF (BP_VAR_R );
454
+ ZEND_VM_C_LABEL (compare_values_any_type ):
455
+
454
456
if (Z_TYPE_P (op1 ) != Z_TYPE_P (op2 )) {
455
- /* They are not identical, return false. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */
457
+ /* Only VAR can be indirect */
458
+ if (UNEXPECTED (((OP1_TYPE & IS_VAR ) && Z_TYPE_P (op1 ) == IS_INDIRECT ) || ((OP2_TYPE & IS_VAR ) && Z_TYPE_P (op2 ) == IS_INDIRECT ))) {
459
+ ZVAL_DEINDIRECT (op1 );
460
+ ZVAL_DEINDIRECT (op2 );
461
+ ZEND_VM_C_GOTO (compare_values_any_type );
462
+ }
463
+ /* Only VAR and CV can be references */
464
+ if (UNEXPECTED (((OP1_TYPE & (IS_VAR |IS_CV )) && Z_ISREF_P (op1 )) || ((OP2_TYPE & (IS_VAR |IS_CV )) && Z_ISREF_P (op2 )))) {
465
+ ZVAL_DEREF (op1 );
466
+ ZVAL_DEREF (op2 );
467
+ if (Z_TYPE_P (op1 ) == Z_TYPE_P (op2 )) {
468
+ ZEND_VM_C_GOTO (compare_values );
469
+ }
470
+ }
471
+ /* Only CV can be undef */
472
+ if (UNEXPECTED (((OP1_TYPE & IS_CV ) && Z_ISUNDEF_P (op1 )) || ((OP2_TYPE & IS_CV ) && Z_ISUNDEF_P (op2 )) )) {
473
+ /* Convert undef to null, check if they're identical */
474
+ if (Z_TYPE_P (op1 ) == IS_UNDEF ) {
475
+ op1 = ZVAL_UNDEFINED_OP1 ();
476
+ }
477
+ if (Z_TYPE_P (op2 ) == IS_UNDEF ) {
478
+ op2 = ZVAL_UNDEFINED_OP2 ();
479
+ }
480
+ result = Z_TYPE_P (op1 ) == Z_TYPE_P (op2 );
481
+ ZEND_VM_C_GOTO (return_result_maythrow );
482
+ }
483
+ /* They are not identical, return false. This has to check for __destruct errors */
456
484
FREE_OP1 ();
457
485
FREE_OP2 ();
458
486
ZEND_VM_SMART_BRANCH (0 , 1 );
459
487
return ;
460
488
}
489
+ ZEND_VM_C_LABEL (compare_values ):
461
490
if (Z_TYPE_P (op1 ) <= IS_TRUE ) {
491
+ if (((OP1_TYPE & IS_CV ) || (OP2_TYPE & IS_CV )) && UNEXPECTED (Z_TYPE_P (op1 ) == IS_UNDEF )) {
492
+ /* They are both undefined - fetch them to emit the undefined variable warnings. */
493
+ op1 = ZVAL_UNDEFINED_OP1 ();
494
+ op2 = ZVAL_UNDEFINED_OP2 ();
495
+ ZEND_VM_SMART_BRANCH (1 , 1 );
496
+ return ;
497
+ }
462
498
/* They are identical, return true */
463
- /* This has to check for undefined variable errors when IS_NULL is possible. */
499
+ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */
464
500
FREE_OP1 ();
465
501
FREE_OP2 ();
466
- ZEND_VM_SMART_BRANCH (1 , 1 );
502
+ ZEND_VM_SMART_BRANCH (1 , 0 );
467
503
return ;
468
504
}
469
505
switch (Z_TYPE_P (op1 )) {
@@ -491,9 +527,19 @@ ZEND_VM_C_LABEL(free_nothrow):
491
527
case IS_OBJECT :
492
528
result = (Z_OBJ_P (op1 ) == Z_OBJ_P (op2 ));
493
529
break ;
530
+ case IS_REFERENCE :
531
+ /* Both are references */
532
+ op1 = Z_REFVAL_P (op1 );
533
+ op2 = Z_REFVAL_P (op2 );
534
+ ZEND_VM_C_GOTO (compare_values_any_type );
535
+ case IS_INDIRECT :
536
+ op1 = Z_INDIRECT_P (op1 );
537
+ op2 = Z_INDIRECT_P (op2 );
538
+ ZEND_VM_C_GOTO (compare_values_any_type );
494
539
default :
495
540
result = 1 ;
496
541
}
542
+ ZEND_VM_C_LABEL (return_result_maythrow ):
497
543
/* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */
498
544
FREE_OP1 ();
499
545
FREE_OP2 ();
@@ -503,26 +549,61 @@ ZEND_VM_C_LABEL(free_nothrow):
503
549
ZEND_VM_COLD_CONSTCONST_HANDLER (17 , ZEND_IS_NOT_IDENTICAL , CONST |TMP |VAR |CV , CONST |TMP |VAR |CV , SPEC (COMMUTATIVE ))
504
550
{
505
551
USE_OPLINE
506
- zval * op1 , * op2 ;
552
+ zval * op1 , * op2 ;
507
553
zend_bool result ;
508
554
509
555
SAVE_OPLINE ();
510
- op1 = GET_OP1_ZVAL_PTR_DEREF (BP_VAR_R );
511
- op2 = GET_OP2_ZVAL_PTR_DEREF (BP_VAR_R );
556
+ op1 = GET_OP1_ZVAL_PTR_UNDEF (BP_VAR_R );
557
+ op2 = GET_OP2_ZVAL_PTR_UNDEF (BP_VAR_R );
558
+ ZEND_VM_C_LABEL (compare_values_any_type ):
512
559
513
560
if (Z_TYPE_P (op1 ) != Z_TYPE_P (op2 )) {
561
+ /* Only VAR can be indirect */
562
+ if (UNEXPECTED (((OP1_TYPE & IS_VAR ) && Z_TYPE_P (op1 ) == IS_INDIRECT ) || ((OP2_TYPE & IS_VAR ) && Z_TYPE_P (op2 ) == IS_INDIRECT ))) {
563
+ ZVAL_DEINDIRECT (op1 );
564
+ ZVAL_DEINDIRECT (op2 );
565
+ ZEND_VM_C_GOTO (compare_values_any_type );
566
+ }
567
+ /* Only VAR and CV can be references */
568
+ if (UNEXPECTED (((OP1_TYPE & (IS_VAR |IS_CV )) && Z_ISREF_P (op1 )) || ((OP2_TYPE & (IS_VAR |IS_CV )) && Z_ISREF_P (op2 )))) {
569
+ ZVAL_DEREF (op1 );
570
+ ZVAL_DEREF (op2 );
571
+ if (Z_TYPE_P (op1 ) == Z_TYPE_P (op2 )) {
572
+ ZEND_VM_C_GOTO (compare_values );
573
+ }
574
+ }
575
+ /* Only CV can be undef */
576
+ if (UNEXPECTED (((OP1_TYPE & IS_CV ) && Z_ISUNDEF_P (op1 )) || ((OP2_TYPE & IS_CV ) && Z_ISUNDEF_P (op2 )) )) {
577
+ /* Convert undef to null, check if they're not identical */
578
+ if (Z_TYPE_P (op1 ) == IS_UNDEF ) {
579
+ op1 = ZVAL_UNDEFINED_OP1 ();
580
+ }
581
+ if (Z_TYPE_P (op2 ) == IS_UNDEF ) {
582
+ op2 = ZVAL_UNDEFINED_OP2 ();
583
+ }
584
+ result = Z_TYPE_P (op1 ) != Z_TYPE_P (op2 );
585
+ ZEND_VM_C_GOTO (return_result_maythrow );
586
+ }
514
587
/* They are not identical, return true. This has to check for __destruct errors (and undefined variable errors when IS_NULL is possible) */
515
588
FREE_OP1 ();
516
589
FREE_OP2 ();
517
590
ZEND_VM_SMART_BRANCH (1 , 1 );
518
591
return ;
519
592
}
593
+ ZEND_VM_C_LABEL (compare_values ):
520
594
if (Z_TYPE_P (op1 ) <= IS_TRUE ) {
595
+ if (((OP1_TYPE & IS_CV ) || (OP2_TYPE & IS_CV )) && UNEXPECTED (Z_TYPE_P (op1 ) == IS_UNDEF )) {
596
+ /* They are both undefined - fetch them to emit the undefined variable warnings. */
597
+ op1 = ZVAL_UNDEFINED_OP1 ();
598
+ op2 = ZVAL_UNDEFINED_OP2 ();
599
+ ZEND_VM_SMART_BRANCH (0 , 1 );
600
+ return ;
601
+ }
521
602
/* They are identical, return false. */
522
- /* This has to check for undefined variable errors when IS_NULL is possible. */
603
+ /* This has to check for undefined variable errors when IS_UNDEF is possible. (only warns for IS_CV) */
523
604
FREE_OP1 ();
524
605
FREE_OP2 ();
525
- ZEND_VM_SMART_BRANCH (0 , 1 );
606
+ ZEND_VM_SMART_BRANCH (0 , 0 );
526
607
return ;
527
608
}
528
609
switch (Z_TYPE_P (op1 )) {
@@ -550,9 +631,19 @@ ZEND_VM_C_LABEL(free_nothrow):
550
631
case IS_OBJECT :
551
632
result = (Z_OBJ_P (op1 ) != Z_OBJ_P (op2 ));
552
633
break ;
634
+ case IS_REFERENCE :
635
+ /* Both are references */
636
+ op1 = Z_REFVAL_P (op1 );
637
+ op2 = Z_REFVAL_P (op2 );
638
+ ZEND_VM_C_GOTO (compare_values_any_type );
639
+ case IS_INDIRECT :
640
+ op1 = Z_INDIRECT_P (op1 );
641
+ op2 = Z_INDIRECT_P (op2 );
642
+ ZEND_VM_C_GOTO (compare_values_any_type );
553
643
default :
554
644
result = 1 ;
555
645
}
646
+ ZEND_VM_C_LABEL (return_result_maythrow ):
556
647
/* Check if freeing the operands (e.g. __destruct(), freeing resources (not sure about that), etc threw an exception before setting the result or branching */
557
648
FREE_OP1 ();
558
649
FREE_OP2 ();
0 commit comments