Skip to content

Commit 6cf5401

Browse files
committed
Zend: add VM spec for ZEND_VERIFY_TYPE_RETURN for string values
1 parent 9057477 commit 6cf5401

File tree

3 files changed

+1087
-554
lines changed

3 files changed

+1087
-554
lines changed

Zend/zend_vm_def.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4572,6 +4572,77 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_VERIFY_RETURN_TYPE, (((res_info & MAY_BE_REF)
45724572
ZEND_VM_NEXT_OPCODE();
45734573
}
45744574

4575+
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|TMPVAR|CV, UNUSED)
4576+
{
4577+
USE_OPLINE
4578+
zval *retval_ptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4579+
uint32_t pure_type_mask = opline->extended_value;
4580+
4581+
zend_string *str = Z_STR_P(retval_ptr);
4582+
if (OP1_TYPE == IS_CONST) {
4583+
ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
4584+
retval_ptr = EX_VAR(opline->result.var);
4585+
}
4586+
4587+
if (pure_type_mask & MAY_BE_STRING) {
4588+
ZEND_VM_NEXT_OPCODE();
4589+
}
4590+
4591+
if (UNEXPECTED(EX_USES_STRICT_TYPES() || ((pure_type_mask & (MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_BOOL)) == 0))) {
4592+
SAVE_OPLINE();
4593+
zend_verify_return_error(EX(func), retval_ptr);
4594+
HANDLE_EXCEPTION();
4595+
}
4596+
4597+
/* Type preference order: int -> float -> bool */
4598+
zend_long lval = 0;
4599+
double dval = 0;
4600+
uint8_t type = is_numeric_str_function(str, &lval, &dval);
4601+
if (type == IS_LONG) {
4602+
zend_string_release(str);
4603+
if (pure_type_mask & MAY_BE_LONG) {
4604+
ZVAL_LONG(retval_ptr, lval);
4605+
} else if (pure_type_mask & MAY_BE_DOUBLE) {
4606+
ZVAL_DOUBLE(retval_ptr, (double)lval);
4607+
} else {
4608+
ZEND_ASSERT(pure_type_mask & MAY_BE_BOOL);
4609+
ZVAL_BOOL(retval_ptr, lval);
4610+
}
4611+
ZEND_VM_NEXT_OPCODE();
4612+
} else if (type == IS_DOUBLE) {
4613+
if (pure_type_mask & MAY_BE_DOUBLE) {
4614+
zend_string_release(str);
4615+
ZVAL_DOUBLE(retval_ptr, dval);
4616+
ZEND_VM_NEXT_OPCODE();
4617+
} else if (pure_type_mask & MAY_BE_LONG) {
4618+
if (!zend_isnan(dval) && ZEND_DOUBLE_FITS_LONG(dval)) {
4619+
lval = zend_dval_to_lval(dval);
4620+
SAVE_OPLINE();
4621+
if (UNEXPECTED(!zend_is_long_compatible(dval, lval))) {
4622+
zend_incompatible_string_to_long_error(str);
4623+
zend_string_release(str);
4624+
}
4625+
zend_string_release(str);
4626+
ZVAL_LONG(retval_ptr, lval);
4627+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4628+
}
4629+
} else {
4630+
zend_string_release(str);
4631+
ZVAL_BOOL(retval_ptr, dval);
4632+
ZEND_VM_NEXT_OPCODE();
4633+
}
4634+
} else {
4635+
if (pure_type_mask & MAY_BE_BOOL) {
4636+
ZVAL_BOOL(retval_ptr, i_zend_is_true(retval_ptr));
4637+
zend_string_release(str);
4638+
ZEND_VM_NEXT_OPCODE();
4639+
}
4640+
}
4641+
SAVE_OPLINE();
4642+
zend_verify_return_error(EX(func), retval_ptr);
4643+
HANDLE_EXCEPTION();
4644+
}
4645+
45754646
ZEND_VM_COLD_HANDLER(201, ZEND_VERIFY_NEVER_TYPE, UNUSED, UNUSED)
45764647
{
45774648
SAVE_OPLINE();

0 commit comments

Comments
 (0)