Skip to content

Commit 3da764c

Browse files
committed
Zend: add VM spec for ZEND_VERIFY_TYPE_RETURN for string values
1 parent c5caf0b commit 3da764c

3 files changed

Lines changed: 1226 additions & 554 deletions

File tree

Zend/zend_vm_def.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4568,6 +4568,75 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_VERIFY_RETURN_TYPE, (((res_info & MAY_BE_REF)
45684568
ZEND_VM_NEXT_OPCODE();
45694569
}
45704570

4571+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_VERIFY_RETURN_TYPE, (((res_info & MAY_BE_REF) == 0) && op1_info == MAY_BE_STRING), ZEND_VERIFY_RETURN_TYPE_FOR_STRING, CONST|TMP|VAR|CV, UNUSED)
4572+
{
4573+
USE_OPLINE
4574+
zval *op, *result;
4575+
uint32_t pure_type_mask = opline->extended_value;
4576+
4577+
if (UNEXPECTED(EX_USES_STRICT_TYPES() || ((pure_type_mask & MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_BOOL) == 0))) {
4578+
SAVE_OPLINE();
4579+
zend_verify_return_error(EX(func), result);
4580+
HANDLE_EXCEPTION();
4581+
}
4582+
4583+
op = GET_OP1_ZVAL_PTR(BP_VAR_R);
4584+
result = EX_VAR(opline->result.var);
4585+
4586+
/* Would have been elided by optimizer */
4587+
ZEND_ASSERT((pure_type_mask & MAY_BE_STRING) == 0);
4588+
4589+
/* Type preference order: int -> float -> bool */
4590+
zend_long lval = 0;
4591+
double dval = 0;
4592+
uint8_t type = is_numeric_str_function(Z_STR_P(op), &lval, &dval);
4593+
if (type == IS_LONG) {
4594+
if (pure_type_mask & MAY_BE_LONG) {
4595+
ZVAL_LONG(result, lval);
4596+
} else if (pure_type_mask & MAY_BE_DOUBLE) {
4597+
ZVAL_DOUBLE(result, (double)lval);
4598+
} else {
4599+
ZEND_ASSERT(pure_type_mask & MAY_BE_BOOL);
4600+
ZVAL_BOOL(result, lval);
4601+
}
4602+
ZEND_VM_NEXT_OPCODE();
4603+
} else if (type == IS_DOUBLE) {
4604+
if (pure_type_mask & MAY_BE_DOUBLE) {
4605+
ZVAL_DOUBLE(result, dval);
4606+
ZEND_VM_NEXT_OPCODE();
4607+
} else if (pure_type_mask & MAY_BE_LONG) {
4608+
if (!zend_isnan(dval) && ZEND_DOUBLE_FITS_LONG(dval)) {
4609+
SAVE_OPLINE();
4610+
/* May warn */
4611+
ZVAL_LONG(result, zend_dval_to_lval_safe(dval));
4612+
ZEND_VM_NEXT_OPCODE();
4613+
}
4614+
} else {
4615+
ZVAL_BOOL(result, dval);
4616+
ZEND_VM_NEXT_OPCODE();
4617+
}
4618+
} else {
4619+
if (pure_type_mask & MAY_BE_BOOL) {
4620+
ZVAL_BOOL(result, i_zend_is_true(op));
4621+
ZEND_VM_NEXT_OPCODE();
4622+
}
4623+
}
4624+
SAVE_OPLINE();
4625+
zend_verify_return_error(EX(func), op);
4626+
HANDLE_EXCEPTION();
4627+
/* int to float is always valid even with strict types */
4628+
if (pure_type_mask & MAY_BE_LONG) {
4629+
ZVAL_LONG(result, lval);
4630+
ZEND_VM_NEXT_OPCODE();
4631+
} else if (pure_type_mask & MAY_BE_DOUBLE) {
4632+
ZVAL_DOUBLE(result, (double)lval);
4633+
ZEND_VM_NEXT_OPCODE();
4634+
} else if (pure_type_mask & MAY_BE_BOOL) {
4635+
ZVAL_BOOL(result, lval);
4636+
} else {
4637+
}
4638+
}
4639+
45714640
ZEND_VM_COLD_HANDLER(201, ZEND_VERIFY_NEVER_TYPE, UNUSED, UNUSED)
45724641
{
45734642
SAVE_OPLINE();

0 commit comments

Comments
 (0)