From 391be07f42312180811c95f0a7def9c7c1597b01 Mon Sep 17 00:00:00 2001 From: Daniel Gale-Rosen <5487802+dangrous@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:38:18 -0400 Subject: [PATCH] Merge pull request #51879 from Expensify/arosiclair-fix-parent-report-loop (cherry picked from commit e7267ea47bfc0ef56d1d590b44df19c230599c10) (CP triggered by mountiny) --- src/libs/ReportUtils.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7ad1b72dfebd..cfaa73650bcf 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -756,7 +756,7 @@ function getParentReport(report: OnyxEntry): OnyxEntry { * Returns the root parentReport if the given report is nested. * Uses recursion to iterate any depth of nested reports. */ -function getRootParentReport(report: OnyxEntry): OnyxEntry { +function getRootParentReport(report: OnyxEntry, visitedReportIDs: Set = new Set()): OnyxEntry { if (!report) { return undefined; } @@ -766,10 +766,18 @@ function getRootParentReport(report: OnyxEntry): OnyxEntry { return report; } + // Detect and prevent an infinite loop caused by a cycle in the ancestry. This should normally + // never happen + if (visitedReportIDs.has(report.reportID)) { + Log.alert('Report ancestry cycle detected.', {reportID: report.reportID, ancestry: Array.from(visitedReportIDs)}); + return undefined; + } + visitedReportIDs.add(report.reportID); + const parentReport = getReportOrDraftReport(report?.parentReportID); // Runs recursion to iterate a parent report - return getRootParentReport(!isEmptyObject(parentReport) ? parentReport : undefined); + return getRootParentReport(!isEmptyObject(parentReport) ? parentReport : undefined, visitedReportIDs); } /**