@@ -5439,31 +5439,53 @@ static void zend_verify_inference_def(zend_execute_data *execute_data, const zen
5439
5439
zend_verify_type_inference (EX_VAR (opline -> op1 .var ), opline -> op1_def_type , opline -> op1_type , execute_data , opline , "op1_def" );
5440
5440
}
5441
5441
if (opline -> op2_def_type
5442
- && (opline -> op2_type & (IS_TMP_VAR |IS_VAR |IS_CV ))) {
5442
+ && (opline -> op2_type & (IS_TMP_VAR |IS_VAR |IS_CV ))
5443
+ /* ZEND_FE_FETCH_R[W] does not define a result in the last iteration. */
5444
+ && opline -> opcode != ZEND_FE_FETCH_R
5445
+ && opline -> opcode != ZEND_FE_FETCH_RW ) {
5443
5446
zend_verify_type_inference (EX_VAR (opline -> op2 .var ), opline -> op2_def_type , opline -> op2_type , execute_data , opline , "op2_def" );
5444
5447
}
5445
5448
if (opline -> result_def_type
5446
5449
&& (opline -> result_type & (IS_TMP_VAR |IS_VAR |IS_CV ))
5447
5450
&& opline -> opcode != ZEND_ROPE_INIT
5448
5451
&& opline -> opcode != ZEND_ROPE_ADD
5449
- // Some jump opcode handlers don't set result when it's never read
5452
+ /* Some jump opcode handlers don't set result when it's never read. */
5450
5453
&& opline -> opcode != ZEND_JMP_SET
5451
5454
&& opline -> opcode != ZEND_JMP_NULL
5452
5455
&& opline -> opcode != ZEND_COALESCE
5453
- && opline -> opcode != ZEND_ASSERT_CHECK ) {
5456
+ && opline -> opcode != ZEND_ASSERT_CHECK
5457
+ /* Smart branches may not declare result. */
5458
+ && !zend_is_smart_branch (opline )
5459
+ /* Calls only initialize result when returning from the called function. */
5460
+ && opline -> opcode != ZEND_DO_FCALL
5461
+ && opline -> opcode != ZEND_DO_ICALL
5462
+ && opline -> opcode != ZEND_DO_UCALL
5463
+ && opline -> opcode != ZEND_DO_FCALL_BY_NAME
5464
+ /* ZEND_FE_FETCH_R[W] does not define a result in the last iteration. */
5465
+ && opline -> opcode != ZEND_FE_FETCH_R
5466
+ && opline -> opcode != ZEND_FE_FETCH_RW ) {
5454
5467
zend_verify_type_inference (EX_VAR (opline -> result .var ), opline -> result_def_type , opline -> result_type , execute_data , opline , "result_def" );
5468
+
5469
+ /* Verify return value in the context of caller. */
5470
+ if ((opline -> opcode == ZEND_RETURN || opline -> opcode == ZEND_RETURN_BY_REF )
5471
+ && execute_data -> prev_execute_data
5472
+ && execute_data -> prev_execute_data -> func
5473
+ && ZEND_USER_CODE (execute_data -> prev_execute_data -> func -> type )) {
5474
+ zend_execute_data * prev_execute_data = execute_data -> prev_execute_data ;
5475
+ const zend_op * opline = execute_data -> prev_execute_data -> opline ;
5476
+ zend_verify_type_inference (ZEND_CALL_VAR (prev_execute_data , opline -> result .var ), opline -> result_def_type , opline -> result_type , prev_execute_data , opline , "result_def" );
5477
+ }
5455
5478
}
5456
5479
}
5457
5480
5458
5481
# define ZEND_VERIFY_INFERENCE_USE () zend_verify_inference_use(execute_data, OPLINE);
5459
- # define ZEND_VERIFY_INFERENCE_DEF () zend_verify_inference_def(execute_data, OPLINE );
5482
+ # define ZEND_VERIFY_INFERENCE_DEF (execute_data , opline ) zend_verify_inference_def(execute_data, opline );
5460
5483
#else
5461
5484
# define ZEND_VERIFY_INFERENCE_USE ()
5462
5485
# define ZEND_VERIFY_INFERENCE_DEF ()
5463
5486
#endif
5464
5487
5465
5488
#define ZEND_VM_NEXT_OPCODE_EX (check_exception , skip ) \
5466
- ZEND_VERIFY_INFERENCE_DEF() \
5467
5489
CHECK_SYMBOL_TABLES() \
5468
5490
if (check_exception) { \
5469
5491
OPLINE = EX(opline) + (skip); \
0 commit comments