1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-12953: SSA integrity verification failed when loading composer classmaps with more than 11k elements

This is a false positive. The cycle detection code stops at 10.000
iterations. Instead of stopping at a fixed amount, make it more robust
by implementing Floyd's cycle detection algorithm.

Closes GH-12954.
This commit is contained in:
Niels Dossche
2023-12-14 20:32:12 +01:00
parent 731734dacb
commit 7585cf6952
2 changed files with 33 additions and 7 deletions

4
NEWS
View File

@@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.2.15
- Core:
. Fixed bug GH-12953 (false positive SSA integrity verification failed when
loading composer classmaps with more than 11k elements). (nielsdos)
- Cli:
. Fix incorrect timeout in built-in web server when using router script and
max_input_time. (ilutov)

View File

@@ -122,7 +122,7 @@ void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ex
/* Vars */
for (i = 0; i < ssa->vars_count; i++) {
zend_ssa_var *var = &ssa->vars[i];
int use, c;
int use;
uint32_t type = ssa->var_info[i].type;
if (var->definition < 0 && !var->definition_phi && i > op_array->last_var) {
@@ -148,23 +148,45 @@ void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *ex
}
}
c = 0;
FOREACH_USE(var, use) {
if (++c > 10000) {
/* Floyd's cycle detection algorithm, applied for use chain. */
use = var->use_chain;
int second_use = use;
while (use >= 0 && second_use >= 0) {
use = zend_ssa_next_use(ssa->ops, var - ssa->vars, use);
second_use = zend_ssa_next_use(ssa->ops, var - ssa->vars, second_use);
if (second_use < 0) {
break;
}
second_use = zend_ssa_next_use(ssa->ops, var - ssa->vars, second_use);
if (use == second_use) {
FAIL("cycle in uses of " VARFMT "\n", VAR(i));
goto finish;
}
}
FOREACH_USE(var, use) {
if (!is_used_by_op(ssa, use, i)) {
fprintf(stderr, "var " VARFMT " not in uses of op %d\n", VAR(i), use);
}
} FOREACH_USE_END();
c = 0;
FOREACH_PHI_USE(var, phi) {
if (++c > 10000) {
/* Floyd's cycle detection algorithm, applied for phi nodes. */
phi = var->phi_use_chain;
zend_ssa_phi *second_phi = phi;
while (phi && second_phi) {
phi = zend_ssa_next_use_phi(ssa, var - ssa->vars, phi);
second_phi = zend_ssa_next_use_phi(ssa, var - ssa->vars, second_phi);
if (!second_phi) {
break;
}
second_phi = zend_ssa_next_use_phi(ssa, var - ssa->vars, second_phi);
if (phi == second_phi) {
FAIL("cycle in phi uses of " VARFMT "\n", VAR(i));
goto finish;
}
}
FOREACH_PHI_USE(var, phi) {
if (!is_in_phi_sources(ssa, phi, i)) {
FAIL("var " VARFMT " not in phi sources of %d\n", VAR(i), phi->ssa_var);
}