Skip to content

Commit 9eba1d8

Browse files
committed
Fix variance verification for anonymous classes
Refactor a bit of variance verification compilation.
1 parent 92cc345 commit 9eba1d8

File tree

1 file changed

+46
-23
lines changed

1 file changed

+46
-23
lines changed

Zend/zend_compile.c

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4114,6 +4114,27 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
41144114
}
41154115
/* }}} */
41164116

4117+
4118+
static
4119+
void _backup_unverified_variance_types(HashTable *unverified_types,
4120+
HashTable **prev_unverified_types)
4121+
{
4122+
zend_hash_init(unverified_types, 0, NULL, NULL, 1);
4123+
*prev_unverified_types = CG(unverified_types);
4124+
CG(unverified_types) = unverified_types;
4125+
}
4126+
4127+
static void _compile_verify_variance(HashTable *unverified_types)
4128+
{
4129+
zend_string *lcname;
4130+
ZEND_HASH_FOREACH_STR_KEY(unverified_types, lcname) {
4131+
zend_op *opline = get_next_op();
4132+
opline->op1_type = IS_CONST;
4133+
opline->opcode = ZEND_VERIFY_VARIANCE;
4134+
LITERAL_STR(opline->op1, lcname);
4135+
} ZEND_HASH_FOREACH_END();
4136+
}
4137+
41174138
void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel);
41184139

41194140
void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
@@ -4125,16 +4146,29 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
41254146
zend_op *opline;
41264147

41274148
if (class_ast->kind == ZEND_AST_CLASS) {
4128-
uint32_t dcl_opnum = get_next_op_number();
4129-
zend_compile_class_decl(class_ast, 0);
4130-
/* jump over anon class declaration */
4131-
opline = &CG(active_op_array)->opcodes[dcl_opnum];
4132-
if (opline->opcode == ZEND_FETCH_CLASS) {
4133-
opline++;
4134-
}
4135-
class_node.op_type = opline->result_type;
4136-
class_node.u.op.var = opline->result.var;
4137-
opline->extended_value = get_next_op_number();
4149+
/* backup previous unverified variance list; anon classes are immediately verified */
4150+
HashTable unverified_types;
4151+
HashTable *prev_unverified_types;
4152+
_backup_unverified_variance_types(&unverified_types, &prev_unverified_types);
4153+
4154+
{
4155+
uint32_t dcl_opnum = get_next_op_number();
4156+
zend_compile_class_decl(class_ast, 0);
4157+
/* jump over anon class declaration */
4158+
opline = &CG(active_op_array)->opcodes[dcl_opnum];
4159+
if (opline->opcode == ZEND_FETCH_CLASS) {
4160+
opline++;
4161+
}
4162+
class_node.op_type = opline->result_type;
4163+
class_node.u.op.var = opline->result.var;
4164+
opline->extended_value = get_next_op_number();
4165+
}
4166+
4167+
_compile_verify_variance(&unverified_types);
4168+
4169+
zend_hash_destroy(&unverified_types);
4170+
CG(unverified_types) = prev_unverified_types;
4171+
41384172
} else {
41394173
zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
41404174
}
@@ -8135,26 +8169,15 @@ void zend_compile_top_stmt(zend_ast *ast) /* {{{ */
81358169

81368170
/* Compile decl stmts */
81378171
{
8138-
zend_string *lcname;
81398172
HashTable unverified_types;
81408173
HashTable *prev_unverified_types;
8141-
zend_hash_init(&unverified_types, 0, NULL, NULL, 1);
8142-
prev_unverified_types = CG(unverified_types);
8143-
CG(unverified_types) = &unverified_types;
8174+
_backup_unverified_variance_types(&unverified_types, &prev_unverified_types);
81448175

81458176
for (p = first_decl; p < last_decl; ++p) {
81468177
zend_compile_top_stmt(*p);
81478178
}
81488179

8149-
/* todo: emit ZEND_VERIFY_VARIANCE */
8150-
ZEND_HASH_FOREACH_STR_KEY(&unverified_types, lcname) {
8151-
zend_op *opline = get_next_op(CG(active_op_array));
8152-
8153-
opline->op1_type = IS_CONST;
8154-
opline->opcode = ZEND_VERIFY_VARIANCE;
8155-
LITERAL_STR(opline->op1, lcname);
8156-
8157-
} ZEND_HASH_FOREACH_END();
8180+
_compile_verify_variance(&unverified_types);
81588181

81598182
zend_hash_destroy(&unverified_types);
81608183
CG(unverified_types) = prev_unverified_types;

0 commit comments

Comments
 (0)