While most other exceptions aren't possible when QM_ASSIGN is used
instead of ASSIGN, we still have to watch out for an undef var
notice being promoted to an exception.
We were not inferring anything for the ASSIGN_STATIC_PROP_REF
result type at all, leaving it as an empty type. In the test
case this results in a live range being incorrectly eliminated,
but this could break in all kinds of other ways as well..
This was leaking memory for pre-inc/dec of a refcounted typed
property if the result was not used.
The code to do this was unnecessarily complicated, we can base
this on the zend_jit_inc/dec_typed_prop() helper and copy to the
result afterwards.
We have an invariant that an array value type is set if and only
if an array key type is set, which is violated for the case of
undef values for always invalid keys.
While technically legal, this may cause unexpected situations
(in this example, setting an FE_FREE operand to constant null)
and is suboptimal anyway. It's better to preserve the vacuous type
and drop it later (though we currently don't implement this).
This can happen in degenerate cases where we know that the
SWITCH_STRING argument is not refcounted. We should be treating it
in the same way as SWITCH_LONG here.
The mod_by_zero and negative_shift helper may also be used by
ASSIGN_OP, in which case there is not necessarily a result operand.
If the stars aligned just right, this used to clobber other parts
of the call frame.
For these two helpers, check whether the result_type is TMP/VAR
before setting to UNDEF:
The evaluation of the initializer may throw. This could be refined
by checking whether the initializer is a constant AST. For now
just fix the miscompile.
We should report the undefined variable here and convert it to
null. Passing on undef is particularly insidious here, because
a write_dimension handler may insert it into a hash table
(observed with WeakMap).
This issue is properly fixed by GH-7121 on master. For older
branches, disable the use of range information in SCCP, to
reduce impact of potentially incorrect ranges.
Literal compaction was incorrectly assuming that literals with
the same base literal and the same number of related literals
would be equal. Maybe that was the case historically, but at
least it isn't true in PHP 8, where FETCH_CONSTANT and INIT_METHOD
have distinct literals at the second position.
Fix this by making the cache key a concatenation of all literals,
rather than just the base literal. We still distinguish the number
of related literals based on a bias added to the string hash.