From 92816d9ea1d9db82b90d932673bcfe20f893ef03 Mon Sep 17 00:00:00 2001 From: "Andrea Grazioso (agr-odoo)" Date: Wed, 25 Nov 2020 08:48:00 +0000 Subject: [PATCH] [FIX] base: avoid infinite recursion on attachments search Steps to reproduce: Create a new local Odoo DB Create another company on the DB install the CRM module Create an opportunity on the CRM app for each company. Execute This server action (CHANGE THE res_id TO THE IDs OF THE OPPORTUNITY CREATED): ``` for _ in range(0, 300): for _ in range (0, 75): env['ir.attachment'].sudo().create({'name': 'test','res_model': 'crm.lead', 'res_id': 31, 'type': 'binary'}) for _ in range (0, 75): env['ir.attachment'].sudo().create({'name': 'test','res_model': 'crm.lead', 'res_id': 45, 'type': 'binary'}) ``` go to the Settings / Technical / Database Structure / Attachments. Server will look in endless call because the search try to retrieve `limit` records, but after applying company record rule we have `limit - e`, so it begin a second search for e records. Even the second search will look for limit and possibly will find less, starting a third... If the sub call is aware of how much records we actually need after checking permission, we can return the recordset if we have collected enough opw-2369722 closes odoo/odoo#62456 X-original-commit: 6a8f28c4d0f9df7cd8451f4caf4f3bf7d64330da Signed-off-by: agr-odoo --- odoo/addons/base/models/ir_attachment.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/odoo/addons/base/models/ir_attachment.py b/odoo/addons/base/models/ir_attachment.py index a8d5ce90672..deb457ba438 100644 --- a/odoo/addons/base/models/ir_attachment.py +++ b/odoo/addons/base/models/ir_attachment.py @@ -489,11 +489,14 @@ class IrAttachment(models.Model): result = [id for id in orig_ids if id in ids] # If the original search reached the limit, it is important the - # filtered record set does so too. When a JS view recieve a - # record set whose length is bellow the limit, it thinks it - # reached the last page. - if len(orig_ids) == limit and len(result) < len(orig_ids): - result.extend(self._search(args, offset=offset + len(orig_ids), + # filtered record set does so too. When a JS view receive a + # record set whose length is below the limit, it thinks it + # reached the last page. To avoid an infinite recursion due to the + # permission checks the sub-call need to be aware of the number of + # expected records to retrieve + if len(orig_ids) == limit and len(result) < self._context.get('need', limit): + need = self._context.get('need', limit) - len(result) + result.extend(self.with_context(need=need)._search(args, offset=offset + len(orig_ids), limit=limit, order=order, count=count, access_rights_uid=access_rights_uid)[:limit - len(result)])