Skip to content

[BUGFIX] Restore Context and DI container state#734

Open
sbuerk wants to merge 1 commit into
mainfrom
frontendrequest-context-leak
Open

[BUGFIX] Restore Context and DI container state#734
sbuerk wants to merge 1 commit into
mainfrom
frontendrequest-context-leak

Conversation

@sbuerk

@sbuerk sbuerk commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

FrameworkState::push()/pop() back up and restore framework state around
frontend sub-requests fired with executeFrontendSubRequest(). Two pieces of
global state were not covered so far: the Context singleton and the globally
registered dependency injection container.

executeFrontendSubRequest() boots the frontend application through
Bootstrap::init(), which registers a fresh container and fills the Context
with the aspects of the frontend request, most notably the language aspect. As
neither was restored afterwards, code running after a sub-request within the
test scope silently continued with frontend request state, for instance Extbase
repository calls resolving records in the language of the sub-request instead of
the default language.

push() now stashes a clone of the current Context along with the container
instance, reset() applies a pristine Context and drops the container, and
pop() puts both back in place. Context is a singleton whose instance
reference is held in many places, so its aspects are copied over using
reflection instead of exchanging the object itself.

The class is further hardened along the way: a State array shape is declared
and applied to the state stack payload, giving proper type information for the
pushed and popped values, and pop() now throws a dedicated exception instead
of running into undefined array access when the stack is empty.

Related core changes

Test results

Local quality gates of this repository (PHP 8.2, podman), all green:

  • Build/Scripts/runTests.sh -s cgl -n
  • Build/Scripts/runTests.sh -s lint
  • Build/Scripts/runTests.sh -s phpstan
  • Build/Scripts/runTests.sh -s unit — 127 tests, 337 assertions

Core side verification runs through the linked change 94945.

Release line: main (10.x). A backport to older branches can be considered
later.

FrameworkState::push()/pop() back up and restore framework state
around frontend sub-requests fired with executeFrontendSubRequest().
Two pieces of global state were not covered so far: the Context
singleton and the globally registered dependency injection
container.

executeFrontendSubRequest() boots the frontend application through
Bootstrap::init(), which registers a fresh container and fills the
Context with the aspects of the frontend request, most notably the
language aspect. As neither was restored afterwards, code running
after a sub-request within the test scope silently continued with
frontend request state, for instance Extbase repository calls
resolving records in the language of the sub-request instead of the
default language.

push() now stashes a clone of the current Context along with the
container instance, reset() applies a pristine Context and drops the
container, and pop() puts both back in place. Context is a singleton
whose instance reference is held in many places, so its aspects are
copied over using reflection instead of exchanging the object
itself.

The core change identifying the leak is:

https://review.typo3.org/c/Packages/TYPO3.CMS/+/94931

It works around the leak in the affected test case by resetting the
language aspect by hand. That workaround is verified to be obsolete
with this patch by the core change:

https://review.typo3.org/c/Packages/TYPO3.CMS/+/94945

which requires this branch, runs the core test suites against it and
reverts the workaround again.

The class is further hardened along the way: a State array shape is
declared and applied to the state stack payload, giving proper type
information for the pushed and popped values, and pop() now throws a
dedicated exception instead of running into undefined array access
when the stack is empty.

Releases: main, 10
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.

1 participant