Problem/Motivation
The Layout builder module does not protect against recursion. If a Block Plugin which renders an entity is placed inside the same entity's layout, you will receive "Maximum function nesting level" errors. This was originally reported in #2976152: Don't allow placing a Custom Block in the layout override for itself or a default layout, and is being mitigated in that issue by hiding known Block Plugins that cause this issue.
Steps to reproduce
We can work over the default "basic page" content type
1. Create a node for basic page content type.
2. Enable the core module "Layout Builder"
3. Create a view to show basic pages as a block:
- With contextual filter by "content ID"
- With a show as "content" and display as "default"
4. Alter the basic page "manage display" to show "default" as "layout builder"
5. Add to layout builder the block that you created at 3 step.
6. Show the node that you created at 1 step and should get the error "The website encountered an unexpected error. Please try again later." and at drupal log this is "Error: Xdebug has detected a possible infinite loop, and aborted your script with a stack depth of '256' frames in Drupal\Component\Plugin\PluginBase->__construct() (line 53 of /var/www/html/contributedrupal10/core/lib/Drupal/Component/Plugin/PluginBase.php)."
Proposed resolution
The mitigation is fine for now, but the Layout builder should have higher level recursion protection, similar to what the Entity Reference formatter does today.
Remaining tasks
Write a patch and tests.
User interface changes
None.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #108 | 2979184-108--reroll-11.x.patch | 42.31 KB | robert-arias |
| #105 | 2979184-105-reroll-10-3.patch | 22.02 KB | kevinquillen |
| #101 | 2979184-nr-bot.txt | 9.72 KB | needs-review-queue-bot |
| #90 | diff-90-87.patch | 1014 bytes | vacho |
| #90 | 2979184-90.patch | 37.23 KB | vacho |
Issue fork drupal-2979184
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
samuel.mortensonI didn't have time to find a fix for this, but here's a failing test.
Comment #4
tedbow@samuel.mortenson didn't know you were working on this 😉
Including my fix and test and your test.
Comment #6
tedbowcomedy of errors today 🎭
I also forgot group.
Comment #9
tedbowJust removing some debug code I left in.
Not sure why
Drupal\Tests\layout_builder\Kernel\LayoutBuilderFieldLayoutCompatibilityTest::testCompatibilityis failingComment #12
xjmThis mitigation presumably works for core plugins, but what about contrib? If it's not mitigated by a contrib plugin that has the issue, then I think this'd be a major bug.
Comment #13
tim.plunkettBumping to major per #2977309-8: Adding a view that will render the current entity to Layout Builder causes a WSOD and closing that as a duplicate.
Comment #14
bendeguz.csirmaz commentedHere's a reroll of #9.
Comment #16
tim.plunkettComment #17
bnjmnmThe test failures for
Drupal\Tests\layout_builder\Kernel\LayoutBuilderFieldLayoutCompatibilityTest::testCompatibilityandDrupal\Tests\layout_builder\Kernel\LayoutBuilderInstallTest::testCompatibilityare due toassertFieldAttributes()being called on the same entity multiple times in a the same Kernel test. It renders the entity as part of the test, and since those calls are part of the same request, the recursion counter increases and prevents rendering on any calls after the first.I'm not yet sure how to best address this. It could be resolved by converting the tests to Functional, but I'd like to be sure there isn't a more straightforward option before doing that much refactoring and slowing down the tests.
Comment #18
tim.plunkettIf performance is that much of a concern, the test could use reflection to make the counter public and reset it.
Comment #19
bnjmnmI rerolled the patch and fixed the test failures, which is uploaded here.
I then checked to see if the tests added by this issue still failed without the fix. They do not fail locally - adding a test only patch to confirm that is the case overall. It's not yet clear if the tests need to be rewritten or if this issue was fixed as a result of another recent change. Sharing the results here to see if someone may be aware of a recent commit that may have addressed this.
Comment #20
bnjmnmIn this patch:
Drupal\layout_builder\EventSubscriber\BlockComponentRenderArrayComment #22
jhedstromPatch in #20 no longer applies.
It would be good to re-upload a test-only patch as well since the one in #20 never ran.
Comment #23
aleevasRerolled patch from 20
Comment #25
aleevasNext patch for fix it
Comment #26
Percy101 commentedI could apply the patch, so no reroll is needed
Comment #27
tim.plunkettWhy revision? I don't believe LB uses revisions this way. Also, why not use the getTempstoreKey() method on section storage? That takes into account language, which this doesn't.
Which logger is this? Also, while exception messages aren't translated, I believe logged messages are supposed to be.
Instead of embedding Views-specific logic here, what about another event subscriber dedicated to this? And if recursion is detected, it stops the event from propagating?
I don't believe the trailing comma is necessary. Also instead of using list(), could dereference the explode with [0]
=== please
Is this a system error? Why not use the LB logger (and inject it?)
This is no longer needed after #3065474: An error occurs when viewing an entity after removing all layout sections and Quickedit module enabled.
Nit, missing a blank line and this should be protected
Please rewrite the test to use
starkDon't usually see this in test methods, why is it here?
Nit: switch to single quotes
Remove this, please
Nit: protected
Comment #28
aleevasAdded fix for 5-13 notices from #27
Still needs work on 1-4
Comment #29
hardik_patel_12 commentedReapplying #28 patch. solving error of
Comment #30
hardik_patel_12 commentedComment #32
bnjmnmAnother instance of
$this->getLogger()that should be replaced with an injected logger, and the string translated.Tests are failing because a new argument was added to the constructor without a default value. An example of how to do this can be found at
\Drupal\layout_builder\Controller\ChooseBlockController::__construct, look at the $current_user variable is implemented.Comment #33
dhirendra.mishra commentedlet me pick up this....
Comment #34
dhirendra.mishra commentedPlease review this as this addresses above comment.
Comment #36
hardik_patel_12 commentedCovered points mentioned in #32, kindly review a new patch.
Comment #38
bnjmnmt()is not automatically available in this class. It can be made available withDrupal\Core\StringTranslation\StringTranslationTrait;Also, this function should not be concatenating a string with variables, use placeholders instead.
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Rend...
This change looks good. Some of the test failures in the patch are because the unit tests need to be updated so the new LoggerInterface arg is taken into account. Instances of
new BlockComponentRenderArray(), need the logger argument added.Comment #39
swatichouhan012 commentedComment #40
swatichouhan012 commentedI have covered point first of #36, and also fixed coding issues of patch.
Comment #41
swatichouhan012 commentedComment #42
dhirendra.mishra commentedComment #43
hardik_patel_12 commentedNeeds to include logger argument in instances of new BlockComponentRenderArray() in failed test files.
Comment #45
swatichouhan012 commentedAdded logger variable in test files, lets see if test got pass.
Comment #47
bnjmnmThanks @swatichouhan012
The logger should be added similar to how $this->account is added. It will look something like
$this->prophesize(LoggerInterface::class)When working with tests, you may find it easier to set up tests locally instead of waiting over an hour for DrupalCI to run the full test suite. A unit test like this will run in seconds. Here's addiitonal info on running tests from the command line. If you have PHPStorm, integrating PHPUnit tests makes it even easier to test locally.
Comment #49
hardik_patel_12 commentedSolving failed test cases.
Comment #50
tim.plunkettMust be removed
Comment #51
mrinalini9 commentedRemoved
core: 8.xfrom #49 as mentioned in #50, please review.Comment #53
ravi.shankar commentedWorking on this.
Comment #54
ravi.shankar commentedHere I have tried to fix failed tests.
Comment #57
fskreuz commentedCurrently, I have one menu that's placed twice on the page (a problem on its own, but that's what I have at the moment). The menu also uses Menu Item Extras so that we can build a mega menu with one of the instances. Left alone, the setup would generate the warnings because:
1. Menu Item Content instances (the menu links) generate the same
$recursive_render_idtowards the same thing, instead of two independent renders of the link from two separate instances of the menu.2. The Menu Item Extras's use of the
rendertwig filter to check for an empty render array. This also generates the same$recursive_render_idand counts towards the same thing, should the render filter encounter that same link.In total, I would get 4 warnings for just one menu item (2 links x 2 twig render). Do that for each menu link in the menu, and my db log is flooded with warnings. The first case (separate renders counted the same) is something that could easily be done with other entities via other methods (e.g. two views rendering the same entity with the same display). And the use of
renderin twig is a known workaround in themes.I have not found a solution on my end. This may be a non-issue even (I could be doing it wrong?). Just posting my findings.
Comment #60
tim.plunkettClosed #3069367: Unable to use layout builder - consumes all memory as a duplicate
Comment #62
joshmillerRe-roll against 9.3.6 ...
Comment #64
anchal_gupta commentedRe-roll against #62. please review it.
Comment #65
suresh prabhu parkala commentedPatch did not apply. Here is the re-roll. Please review.
Comment #66
andrea.cividini commentedI had patch #65 already applied to my project and I applied patch #8 from this ticket https://www.drupal.org/project/drupal/issues/2940605#comment-14687218 and they seemed to conflict.
After applying the new patch, the LB protection mechanism provided by patch #65 was blocking all the rendering.
After removing patch #65 I was able to do batch rendering without any error log or message.
Comment #68
vacho commentedI apply the patch $65 but I have this issue on browser:
Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 32768 bytes) in /var/www/html/web/core/lib/Drupal/Core/Utility/Error.php on line 1
Comment #69
vacho commentedI rerolled and fixed these items:
- Core module quickedit has been removed https://www.drupal.org/node/3252839
Comment #70
dk-massive commentedIn a site I am managing, patches 65 and 69 causes Paragraphs using Layout Builder in their view mode to not render their content.
Comment #71
vacho commentedComment #72
vacho commentedI fixed some test issues here
Als @dk-massive, following the task steps and last patch I got fixed this issue.
Comment #73
vacho commentedI fixed another test issues
Comment #74
vacho commentedComment #75
vacho commentedFixing some another testing issues.
Comment #76
nikhil_110 commentedFixing Cs Issue #75
Comment #77
nikhil_110 commentedComment #78
smustgrave commentedTest failures.
Comment #79
dk-massive commentedFixed test issue.
Comment #81
dk-massive commentedfix testing issue
Comment #82
dk-massive commentedComment #83
dk-massive commentedfix test. adjust test to use prophesize for logger service.
Comment #84
smustgrave commentedtrigger_error messages will have to be updated. Currently says D9
Also a change record will be needed for the new parameter in the service.
Comment #85
vacho commentedAbout to trigger_error message there is one a core/modules/layout_builder/src/EventSubscriber/BlockComponentRenderArray.php that is:
As I see says "It is required before Drupal 9.0.0" I don't think is needed to change the core version to 10 in this message. D9 is still in production, also the message says "before...".
Comment #86
smustgrave commented9.0.0 is no longer supported. Hasn’t been for some time.
Also can’t be made required in a minor release which this would be. So would have to be done in a major release. So if this trying to get in for 10.1 or would have to be triggered in 10.1 and required in 11
Comment #87
vacho commentedOk, @smustgrave sounds logic.
I modified the @trigger_error message.
About "change record" for the service. I think this should be added to this list manually https://www.drupal.org/list-changes/drupal
after or at the time that this issue merged.
Comment #88
vacho commentedComment #89
smustgrave commentedThanks but still needs a change record that will be added to the trigger_error.
Thought there was a check for it but the trigger_error follows a pattern
Example
Comment #90
vacho commentedAhh, thanks @smustgrave for the guides.
I think was fixed. Pleas review.
Comment #91
vacho commentedComment #94
liam morlandComment #95
smustgrave commentedUnfortunately missed the 10.1 for deprecation. If those can be updated fir 10.2 please.
Comment #96
kevinquillen commentedThe patches #90 fixed the problem for me.
Comment #97
kevinquillen commentedPatch no longer applies to 10.3.x.
Comment #100
gauravvvv commentedComment #101
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #103
mithun sFixed some of the issues related to pipeline and added a commit for the same MR. Still some of the tests are getting failed, keeping the issue status as unchanged.
Thanks!!.
Comment #104
kevinquillen commentedLast patch does not apply to 10.3. Attaching one for 10.3 (I need it).
Comment #105
kevinquillen commentedRe-upping patch from #104 with new files included.
Comment #106
kevinquillen commentedComment #108
robert-arias commentedMR patch for 11.2.x support