Skip to content

fix: stop fixAmps() recursing forever on a navbar link with an entity - #5210

Merged
connortechnology merged 2 commits into
ZoneMinder:masterfrom
nabbi:fix/b5-fixamps-recursion
Oct 11, 2026
Merged

connortechnology merged 2 commits into
ZoneMinder:masterfrom
nabbi:fix/b5-fixamps-recursion

Conversation

@nabbi

@nabbi nabbi commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Automated PR, tested in a zm-holodeck sandbox. An AI agent (Claude Opus 5.5) reproduced the bug on a disposable ZoneMinder built from upstream master 6c0f976c2, wrote this fix and ran the checks below on the same lab. Minimal human review before opening: please review it as you would any contributor's PR.

TL;DR

  • Fixes: Left navbar answers 500 when ZM_WEB_NAVBAR_LINKS contains an HTML entity #5209: the left navbar answers 500 when ZM_WEB_NAVBAR_LINKS contains an HTML entity.
  • Change: fixAmps() becomes one preg_replace() that escapes every & that doesn't start a character reference; a second commit stops the per-page warnings for navbar links without a query string. 1 file, +9/-15.
  • Heads-up, a small behaviour change: which ampersands get escaped changes slightly (table below). Links with entities render again; the escaping is now consistent.
  • Tested: 5 link shapes: 3 answered 500 before, all 5 answer 200 after with the link in the page and no PHP warnings.
Details: change, behaviour changes, checks

Before

Upstream master 6c0f976c2: [entity], [two-entities], [bare-and-entity] HTTP 500 (Allowed memory size of 536870912 bytes exhausted ... functions.php on line 1828); [plain], [bare-amp] 200.

Change

  • web/skins/classic/includes/functions.php fixAmps(): preg_replace('/&(?!#[0-9]+;|#x[0-9a-f]+;|[a-z][a-z0-9]*;)/i', '&', $html) replaces the recursive search. (Passing the missing offset would also stop the recursion, but keeps the old check, which accepted a bare & whenever any ; came later and escaped hex references.)
  • Same file, second commit: read the view of a navbar link only when its href has a query string.

Behaviour changes

Change Who sees it Intended / collateral Alternatives looked into Chosen, why Tested by
Links with an entity render instead of a 500 left-navbar users intended — — probe
A bare & is now escaped even when a ; appears later in the string (was left as is) admins writing navbar links collateral add the missing offset, keep the old check one rule for every &: escape unless it starts a decimal, hex or named reference probe [bare-and-entity]
Hex references (&) are kept (were escaped to &) same collateral — they are valid references probe
No more Undefined array key and parse_str() lines per page log readers intended — — probe

After

Branch at 34a032188 (base 6c0f976c2): 5/5 HTTP 200, link in page, no PHP lines.

Check Result
holodeck checks script tests PASS=28; smoke PASS=11 XFAIL=1 (known); ui suite green apart from known XFAILs

Not run: release-1.38 (same code; the patches apply with git am -3).

refs #5209

🤖 Generated with Claude Code

nabbi and others added 2 commits October 10, 2026 13:28
fixAmps() is declared with one parameter but called itself with a
position, which PHP drops, so every call searched from the first '&'
again. Once ZM_WEB_NAVBAR_LINKS held an entity (&, &ZoneMinder#39;, ...) or a
bare '&' followed later by a ';', rendering the left navbar recursed until
PHP ran out of memory, and every page answered 500 for users who use the
left navbar.

Escape the bare ampersands in one preg_replace() instead. Character
references are matched at the '&' itself, so a bare '&' is no longer
taken as valid because an entity appears later in the string, and
hexadecimal references (') are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
getAdditionalLinksHTML() parsed every left navbar link's href as if it
carried a query string with a view parameter. A link to another site
(https://host/docs) logged 'Undefined array key "query"', a parse_str()
deprecation and 'Undefined array key "view"' on every page view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@connortechnology
connortechnology merged commit f4b4665 into ZoneMinder:master Oct 11, 2026
10 checks passed
connortechnology pushed a commit that referenced this pull request Oct 11, 2026
…#5210)

* fix: stop fixAmps() recursing forever on a navbar link with an entity

fixAmps() is declared with one parameter but called itself with a
position, which PHP drops, so every call searched from the first '&'
again. Once ZM_WEB_NAVBAR_LINKS held an entity (&amp;, &#39;, ...) or a
bare '&' followed later by a ';', rendering the left navbar recursed until
PHP ran out of memory, and every page answered 500 for users who use the
left navbar.

Escape the bare ampersands in one preg_replace() instead. Character
references are matched at the '&' itself, so a bare '&' is no longer
taken as valid because an entity appears later in the string, and
hexadecimal references (&#x27;) are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: read the view of a navbar link only when its href has one

getAdditionalLinksHTML() parsed every left navbar link's href as if it
carried a query string with a view parameter. A link to another site
(https://host/docs) logged 'Undefined array key "query"', a parse_str()
deprecation and 'Undefined array key "view"' on every page view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit f4b4665)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants