diff options
| author | fja-odoo <fja@odoo.com> | 2020-05-13 08:52:12 +0000 |
|---|---|---|
| committer | fja-odoo <fja@odoo.com> | 2020-05-20 13:20:35 +0000 |
| commit | 049745c5fffcd11894cd5f9b38078c993d2ef969 (patch) | |
| tree | 0c52321af364561becd5fe193ddcc4ad9f71cb81 /addons/web_editor/models | |
| parent | e3b4f3ddf43f309eea7272fe78dcbb2eb4e90a6c (diff) | |
[FIX] web_editor: fix _view_get infinite recursion
The _view_get function is a recursive function used to retieve all the
views related to a view (inherited or t-called).
The issue is that by an odd set of circumstances it is possible to have
a loop in the view graph. Resulting in the recursive function being
called until a "maximum recursion depth exceeded" error occurs.
Example of a loop: A t-call B and A inherit from B
This is possible on an update of a view that has been forked by website:
If the view A was doing a t-call on B and is has been duplicated with
the arch modified.
When we update with the changes A now inherit from B instead of t-call B
Since the arch was modified it will not be updated so A will still
t-call B but the inherit_id of A is unchanged so it will be updated to
reference B resulting in a loop.
closes odoo/odoo#51620
X-original-commit: 63e1e84ebd7e609d6e06d83dc0f0092688b013eb
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Diffstat (limited to 'addons/web_editor/models')
| -rw-r--r-- | addons/web_editor/models/ir_ui_view.py | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/addons/web_editor/models/ir_ui_view.py b/addons/web_editor/models/ir_ui_view.py index c56fdadbb6e..a3bfd773a92 100644 --- a/addons/web_editor/models/ir_ui_view.py +++ b/addons/web_editor/models/ir_ui_view.py @@ -224,7 +224,7 @@ class IrUiView(models.Model): # Used by translation mechanism, SEO and optional templates @api.model - def _views_get(self, view_id, get_children=True, bundles=False, root=True): + def _views_get(self, view_id, get_children=True, bundles=False, root=True, visited=None): """ For a given view ``view_id``, should return: * the view itself * all views inheriting from it, enabled or not @@ -238,6 +238,8 @@ class IrUiView(models.Model): _logger.warning("Could not find view object with view_id '%s'", view_id) return self.env['ir.ui.view'] + if visited is None: + visited = [] while root and view.inherit_id: view = view.inherit_id @@ -252,8 +254,8 @@ class IrUiView(models.Model): called_view = self._view_obj(child.get('t-call', child.get('t-call-assets'))) except ValueError: continue - if called_view and called_view not in views_to_return: - views_to_return += self._views_get(called_view, get_children=get_children, bundles=bundles) + if called_view and called_view not in views_to_return and called_view.id not in visited: + views_to_return += self._views_get(called_view, get_children=get_children, bundles=bundles, visited=visited + views_to_return.ids) if not get_children: return views_to_return @@ -263,9 +265,10 @@ class IrUiView(models.Model): # Keep children in a deterministic order regardless of their applicability for extension in extensions.sorted(key=lambda v: v.id): # only return optional grandchildren if this child is enabled - for ext_view in self._views_get(extension, get_children=extension.active, root=False): - if ext_view not in views_to_return: - views_to_return += ext_view + if extension.id not in visited: + for ext_view in self._views_get(extension, get_children=extension.active, root=False, visited=visited + views_to_return.ids): + if ext_view not in views_to_return: + views_to_return += ext_view return views_to_return @api.model |
