-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix GH-17577: JIT packed type guard crash #17584
base: PHP-8.3
Are you sure you want to change the base?
Conversation
ab89b9b
to
b477345
Compare
When a guard check is created for a variable to check if it's a packed array, it is possible that there was no prior type check for that variable. This happens in the global scope for example when the variable aliases. In the test, this causes a dereference of address 8 because the integer element in `$a` is interpreted as an array address. This patch adds a check to see if the guard is handled. If we were not able to determine or guard the type then we also cannot know the array is packed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The patch fixes the problem, but I think it might be better not to add MAY_BE_PACKED_GUARD
in the first place. This may be done by checking op1_info & (MAY_BE_ANY|MAY_BE_UNDEF) == MY_BE_ARRAY
.
What do you think? may be I miss something.
The particular code responsible for setting diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index c138a5bcb0a..8fd0d1323d0 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -1935,7 +1935,8 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
zend_ssa_var_info *info = &tssa->var_info[tssa->ops[idx].op1_use];
- if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)) {
+ if (MAY_BE_PACKED(info->type) && MAY_BE_HASH(info->type)
+ && (info->type & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
info->type |= MAY_BE_PACKED_GUARD;
if (orig_op1_type & IS_TRACE_PACKED) {
info->type &= ~(MAY_BE_ARRAY_NUMERIC_HASH|MAY_BE_ARRAY_STRING_HASH);
@@ -4162,7 +4163,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
}
if ((info & MAY_BE_PACKED_GUARD) != 0
- && (info & MAY_BE_GUARD) == 0
&& (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET)
If I do this, and keep the assertion for the stack type to be |
When a guard check is created for a variable to check if it's a packed array, it is possible that there was no prior type check for that variable. This happens in the global scope for example when the variable aliases. In the test, this causes a dereference of address 8 because the integer element in
$a
is interpreted as an array address and zend_array.u.flags is at offset 8.This patch adds a check to see if the guard is handled.
If we were not able to determine or guard the type is array, then we also cannot know the array is packed.
An alternative I thought about was emitting a type check in this branch, but that can cause incorrect guard motion in case of aliasing. In such case we also shouldn't clear the
MAY_BE_PACKED_GUARD
like it does now.