Codeinwp / Codeinwp/otter-blocks

Single-quoted postContent dynamic tags can exhaust PHP memory

Open
#2,993 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug-report bug-report-triage crash-report
Dominant language
JavaScript
Stars
198
Forks
36
Avg merge
3d 4h
Merged PRs (30d)
30

Description

Summary

A nested Dynamic Content tag using a single-quoted postContent type can recursively render page content until PHP exhausts its memory limit.

Expected behavior: Nested postContent Dynamic Content tags are detected and resolved safely without recursive rendering.

Actual behavior: The frontend request can repeatedly render the same content and terminate with an allowed-memory-size fatal error.

Impact: Affected pages can fail to render for visitors under the configured PHP memory limit.

Customer context

  • Product / area: Otter Blocks Dynamic Content, frontend rendering
  • Version: Telemetry observed versions 3.2.2 and 3.2.3
  • Environment: WordPress 7.1; PHP 8.3.33; 128 MB PHP memory limit
  • Reported error / symptom: Allowed memory size of 134217728 bytes exhausted (tried to allocate 32768 bytes)
  • Impact: 2 fatal-error occurrences across 2 distinct production sites from 2026-08-19 through 2026-08-21.

Reproduction notes

  1. Create or filter post content so it contains a nested Dynamic Content tag with data-type='postContent'.
  2. Render a frontend page that resolves that Dynamic Content value.
  3. The current guard does not recognize the single-quoted nested tag, and repeated content rendering can continue until the PHP memory limit is exhausted.

The exact production markup is unavailable; this reproduction follows the parser-accepted syntax and inspected frontend call path.

Diagnosis

Conclusion

The production fatal points to Dynamic_Content::get_exception_key() while dynamic content is being evaluated. Source inspection confirms a parser/guard mismatch: Dynamic_Content::dynamic_content_regex() accepts both single- and double-quoted data-type values, but Dynamic_Content::mark_exceptions() looks only for the literal double-quoted data-type="postContent". A nested parser-valid single-quoted postContent tag therefore remains unmarked, after which Dynamic_Content::get_content() applies the_content to that post content again. This is a concrete recursive-rendering path consistent with the shutdown-detected memory exhaustion.

Where this likely occurs
  • inc/plugins/class-dynamic-content.phpDynamic_Content::dynamic_content_regex() lines 93-107 accepts data-type values delimited by either quote style.
  • inc/plugins/class-dynamic-content.phpDynamic_Content::get_data() lines 443-472 routes postContent tags to Dynamic_Content::get_content().
  • inc/plugins/class-dynamic-content.phpDynamic_Content::get_content() lines 540-550 builds the exception key, then applies the_content to retrieved post content.
  • inc/plugins/class-dynamic-content.phpDynamic_Content::mark_exceptions() lines 898-912 detects nested tags through the double-quote-specific literal data-type="postContent".
  • inc/plugins/class-dynamic-content.phpDynamic_Content::get_exception_key() lines 943-952 is the telemetry location; it is repeatedly reached during the inferred recursive path.
  • v3.2.3 contains commit f6a47092eca8a8b3e83c98220b90c507341ebf1b (release: fixes), which corrected context selection for this feature but retained the quote-specific guard condition. Telemetry includes 3.2.3 after that release.
Engineering notes

The inspected path is frontend render_block processing: Dynamic_Content::init() registers apply_dynamic_content() on that filter at inc/plugins/class-dynamic-content.php lines 25-32. The loop guard is intended to identify a postContent tag inside the source post before the_content triggers nested block rendering. The failure depends on markup reaching this parser with single-quoted attributes; the report does not include the affected page content, so this exact markup is an evidence-backed reproduction path rather than a confirmed production payload.

The crash is in Otter code, not the bundled Themeisle SDK, and no companion repository is implicated by the supplied telemetry.

Test coverage status

tests/test-dynamic-content.php lines 1171-1221 includes TestDynamicContent::test_post_content_guard_detects_nested_tag_in_context_post, covering the intended recursion guard with a double-quoted tag. No relevant coverage for single-quoted postContent markup was found during inspection. The existing long-content test at lines 710-720 exercises repeated replacements but not recursive postContent rendering.

What to verify or explore next
  • Reproduce frontend rendering of a post whose content contains a nested <o-dynamic data-type='postContent'>…</o-dynamic> tag.
  • Run the Dynamic Content PHPUnit suite with a single-quoted nested-tag case under a bounded PHP memory limit.
  • Check whether block serialization, content migrations, or third-party content filters can emit the single-quoted form in supported editor workflows.
Unknowns / follow-up
  • No structured stack trace or affected post markup was captured by telemetry.
  • The available evidence does not establish how the two affected sites produced the parser-valid single-quoted markup or whether additional malformed/nested markup variants reach the same recursive path.

Confidence

Confidence: 88/100

The fatal occurs in Otter's recursion-guard path, and source inspection shows that the dynamic-content parser accepts single-quoted attributes while the guard only recognizes a double-quoted postContent attribute. This leaves a parser-valid nested tag unguarded and permits recursive frontend rendering.

Crash telemetry

Occurrences 2
Distinct sites 2
First seen 2026-08-19 23:38 UTC
Last seen 2026-08-21 05:12 UTC
Crash location product:inc/plugins/class-dynamic-content.php:951
Request context frontend
Inside Themeisle SDK no
Product versions 3.2.2, 3.2.3
WP versions 7.1
PHP versions 8.3.33
SDK versions 3.3.58, 3.3.59

Source: automated crash report — otter-blocks, fingerprint 0c1564bd69f5bbc3066bb86c49a064fe
Generated by bug-report-triage (ID: bug-report-triage_6a8a8c91010fb7.64532230)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in inc/plugins/class-dynamic-content.php, tracing dynamic_content_regex(), mark_exceptions(), get_data(), and get_content(). Run the Dynamic Content PHPUnit tests, especially tests/test-dynamic-content.php around test_post_content_guard_detects_nested_tag_in_context_post, then add coverage for single-quoted postContent markup. Done means nested tags in either supported quote style are detected without recursive rendering or memory exhaustion.

Written by the indexing model from the issue text.

Assessment

Tech stack
php, wordpress
Domain
frontend, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.