Summary
Optimole can exhaust the PHP memory limit while rewriting URLs in a frontend response that contains a large number of distinct eligible URLs. Expected behavior: frontend output optimization completes without terminating the request under supported site content. Actual behavior: the request terminates with an allowed-memory-size fatal error during URL replacement. Impact: affected visitors receive a failed frontend response instead of the rendered page.
Customer context
- Product / area: Optimole WordPress plugin, frontend output URL replacement
- Version: 4.2.10
- Environment: WordPress 7.1; PHP 7.4.33 and PHP 8.1.2-1ubuntu2.25; 128 MB PHP memory limit in reported crashes
- Integration / third party: Not provided
- Reported error / symptom:
Allowed memory size of 134217728 bytes exhausted (tried to allocate 90112 bytes)
- Impact: 2 occurrences across 2 distinct production sites between 2026-08-21 and 2026-08-25.
Reproduction notes
- Use a frontend request eligible for Optimole output replacement.
- Render a sufficiently large response containing many distinct URLs matching Optimole's image or asset extraction rules.
- Run with a 128 MB PHP memory limit.
- Observed in production: the request can terminate at URL replacement with
Allowed memory size of 134217728 bytes exhausted.
A local runtime reproduction was not performed; exact content size and URL cardinality are unknown.
Diagnosis
Conclusion
Production telemetry records a frontend fatal at inc/manager.php:784. The inspected code buffers the full frontend response, extracts all distinct matching URLs, then applies a full-string preg_replace() once for each URL. This creates a direct memory-exhaustion path for sufficiently large content or high unique-URL cardinality. The reported fatal is in Optimole product code, not Themeisle SDK code.
Where this likely occurs
inc/manager.php — Optml_Manager::process_template_redirect_content() lines 793-817 starts an output buffer for eligible frontend requests and passes the full response to replace_content().
inc/manager.php — Optml_Manager::replace_content() lines 441-533 invokes process_urls_from_content() at lines 525-529 after other whole-content processing.
inc/manager.php — Optml_Manager::extract_urls_from_content() and Optml_Manager::normalize_urls() lines 703-737 collect matching URLs and deduplicate them, with no observed bound on input size or number of unique URLs.
inc/manager.php — Optml_Manager::do_url_replacement() lines 748-785 loops over each extracted URL and assigns a complete preg_replace() result back to $html at line 784, matching the production crash location.
v4.2.10 is release commit 060fd3fe (2026-07-15). The inspected v4.2.9..v4.2.10 diff contains no change to inc/manager.php; blame attributes the replacement loop to b7f67fd7 (2019-12-14). Available history does not establish a regression in 4.2.10.
Engineering notes
The failure surface is the non-partial frontend output-buffer workflow when URL processing reaches do_url_replacement(). The peak memory requirement can grow with both the buffered response size and the count of distinct image or, when CDN processing is active, asset URLs. Two production reports on different PHP versions reached the same fatal location under a 128 MB memory limit. The exact page size, URL count, active Optimole settings, and other plugins on those sites are unavailable.
Test coverage status
tests/test-replacer.php covers functional replacement through test_optimization_url() lines 217-226, test_assets_url() lines 323-358, test_style_replacement() lines 372-379, and test_elementor_data() lines 482-505. These tests assert transformed output for representative content but do not cover large buffered responses, high unique-URL cardinality, peak memory, or the frontend output-buffer hook. No relevant resource-bound coverage was found during inspection.
What to verify or explore next
- May be worth reproducing with the frontend output-buffer workflow, a constrained 128 MB PHP memory limit, and progressively larger HTML containing distinct eligible image and asset URLs.
- If reproducible, checking peak memory for
replace_content() and do_url_replacement() separately may distinguish extraction cost from repeated replacement cost.
- May be worth confirming behavior with CDN asset processing enabled and disabled, since
extract_urls_from_content() expands the eligible extensions when that setting is active.
Unknowns / follow-up
- The telemetry report has no structured stack trace beyond the fatal location.
- The specific response size, number of extracted URLs, and per-site Optimole configuration were not captured.
- No earlier working release boundary is available from the incident evidence.
Confidence
Confidence: 91/100
Behavior inventory: 1. A frontend Optimole URL-replacement request can exhaust PHP memory. Production telemetry pinpoints the fatal at the per-URL replacement loop, and repository inspection confirms that a complete buffered response is repeatedly processed without a content-size or URL-cardinality bound. The path is product code, not the Themeisle SDK.
Crash telemetry
|
|
| Occurrences |
2 |
| Distinct sites |
2 |
| First seen |
2026-08-21 04:36 UTC |
| Last seen |
2026-08-25 09:18 UTC |
| Crash location |
product:inc/manager.php:784 |
| Request context |
frontend |
| Inside Themeisle SDK |
no |
| Product versions |
4.2.10 |
| WP versions |
7.1 |
| PHP versions |
7.4.33, 8.1.2-1ubuntu2.25 |
| SDK versions |
3.3.58, 3.3.59 |
Source: automated crash report — optimole-wp, fingerprint e16d0f7a1b6dbfc263cf3fb43ab3af81
Generated by bug-report-triage (ID: bug-report-triage_6a8e81425e50f1.08531822)
Summary
Optimole can exhaust the PHP memory limit while rewriting URLs in a frontend response that contains a large number of distinct eligible URLs. Expected behavior: frontend output optimization completes without terminating the request under supported site content. Actual behavior: the request terminates with an allowed-memory-size fatal error during URL replacement. Impact: affected visitors receive a failed frontend response instead of the rendered page.
Customer context
Allowed memory size of 134217728 bytes exhausted (tried to allocate 90112 bytes)Reproduction notes
Allowed memory size of 134217728 bytes exhausted.A local runtime reproduction was not performed; exact content size and URL cardinality are unknown.
Diagnosis
Conclusion
Production telemetry records a frontend fatal at
inc/manager.php:784. The inspected code buffers the full frontend response, extracts all distinct matching URLs, then applies a full-stringpreg_replace()once for each URL. This creates a direct memory-exhaustion path for sufficiently large content or high unique-URL cardinality. The reported fatal is in Optimole product code, not Themeisle SDK code.Where this likely occurs
inc/manager.php—Optml_Manager::process_template_redirect_content()lines 793-817 starts an output buffer for eligible frontend requests and passes the full response toreplace_content().inc/manager.php—Optml_Manager::replace_content()lines 441-533 invokesprocess_urls_from_content()at lines 525-529 after other whole-content processing.inc/manager.php—Optml_Manager::extract_urls_from_content()andOptml_Manager::normalize_urls()lines 703-737 collect matching URLs and deduplicate them, with no observed bound on input size or number of unique URLs.inc/manager.php—Optml_Manager::do_url_replacement()lines 748-785 loops over each extracted URL and assigns a completepreg_replace()result back to$htmlat line 784, matching the production crash location.v4.2.10is release commit060fd3fe(2026-07-15). The inspectedv4.2.9..v4.2.10diff contains no change toinc/manager.php; blame attributes the replacement loop tob7f67fd7(2019-12-14). Available history does not establish a regression in 4.2.10.Engineering notes
The failure surface is the non-partial frontend output-buffer workflow when URL processing reaches
do_url_replacement(). The peak memory requirement can grow with both the buffered response size and the count of distinct image or, when CDN processing is active, asset URLs. Two production reports on different PHP versions reached the same fatal location under a 128 MB memory limit. The exact page size, URL count, active Optimole settings, and other plugins on those sites are unavailable.Test coverage status
tests/test-replacer.phpcovers functional replacement throughtest_optimization_url()lines 217-226,test_assets_url()lines 323-358,test_style_replacement()lines 372-379, andtest_elementor_data()lines 482-505. These tests assert transformed output for representative content but do not cover large buffered responses, high unique-URL cardinality, peak memory, or the frontend output-buffer hook. No relevant resource-bound coverage was found during inspection.What to verify or explore next
replace_content()anddo_url_replacement()separately may distinguish extraction cost from repeated replacement cost.extract_urls_from_content()expands the eligible extensions when that setting is active.Unknowns / follow-up
Confidence
Confidence: 91/100
Behavior inventory: 1. A frontend Optimole URL-replacement request can exhaust PHP memory. Production telemetry pinpoints the fatal at the per-URL replacement loop, and repository inspection confirms that a complete buffered response is repeatedly processed without a content-size or URL-cardinality bound. The path is product code, not the Themeisle SDK.
Crash telemetry
product:inc/manager.php:784Source: automated crash report — optimole-wp, fingerprint
e16d0f7a1b6dbfc263cf3fb43ab3af81Generated by bug-report-triage (ID: bug-report-triage_6a8e81425e50f1.08531822)