java-topology/docs/tickets/php-0001-named-arg-linear-scan-compile-time.md
russell@unturf.com 9934133dcf whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
Add 88 new defect entries to HIGH and MEDIUM tables:
  HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
        vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
        tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
        allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
        mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
        linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
        perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002

  MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
          cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
          pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
          ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
          r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
          ovs-0001, onos-0003, odl-0002, jetty-0001

PDF: 976K
2026-03-27 15:23:43 -04:00

65 lines
2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# php-0001 — zend_compile.c: O(n²) linear scan for named argument position
| Field | Value |
|-------|-------|
| ID | php-0001 |
| Target | PHP |
| File | `Zend/zend_compile.c` |
| Lines | 37553766, 3784, 3822 |
| CWE | CWE-407 (Algorithmic Complexity) |
| Severity | HIGH |
| Status | PATCHED |
## Description
`zend_get_arg_num()` performs a linear scan over `fn->common.num_args` entries
to locate a named argument by string comparison:
```c
static uint32_t zend_get_arg_num(const zend_function *fn, const zend_string *arg_name) {
// TODO: Caching?
for (uint32_t i = 0; i < fn->common.num_args; i++) {
zend_arg_info *arg_info = &fn->op_array.arg_info[i];
if (zend_string_equals(arg_info->name, arg_name)) {
return i + 1;
}
}
return (uint32_t) -1;
}
```
This is called from `zend_compile_args()` which iterates over all `args->children`
at compile time. For a function with M parameters called with N named arguments
the total cost is O(N × M). The upstream comment `// TODO: Caching?` acknowledges
the defect.
The companion runtime function `zend_get_arg_offset_by_name()` in
`zend_execute.c` (line 5479) carries the same structure with an explicit
`// TODO: Use a hash table?` comment, and is subject to identical quadratic
behavior on cache miss.
## Reproduction
```php
// Function with 50 named parameters, called with all 50 named — 50×50 = 2500 scans
function wide(
$p0, $p1, $p2, ..., $p49
) {}
// Each named arg triggers zend_get_arg_num linear scan over 50 entries
wide(p49: 1, p48: 2, ..., p0: 50);
```
## Fix
Build a `HashTable` from `arg_name → position` once per function signature and
cache it on the `zend_function` (or use the existing per-opcode cache slot for
the runtime path, which already has infrastructure but is not used for the
compile-time path).
## Complexity
| Metric | Before | After |
|--------|--------|-------|
| Per named-arg lookup | O(M) | O(1) |
| N named args, M params | O(N×M) | O(N + M) |
| Speedup (N=M=50) | 1× | ~50× |