From 90a61b8d3687154b9ac1277f92d936463958d41b Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@craftyjon.com>
Date: Sun, 26 Nov 2023 16:43:06 -0500
Subject: [PATCH] Prevent some issues with recursion on repeat-last-item

Fixes https://gitlab.com/kicad/code/kicad/-/issues/16168
---
 eeschema/sch_sheet_path.cpp      |  5 +++++
 eeschema/tools/sch_edit_tool.cpp | 15 +++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/eeschema/sch_sheet_path.cpp b/eeschema/sch_sheet_path.cpp
index c90dcd46a4..e8f6e15caf 100644
--- a/eeschema/sch_sheet_path.cpp
+++ b/eeschema/sch_sheet_path.cpp
@@ -708,6 +708,11 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet, bool aCheckIntegrity )
             }
             else
             {
+                // If we are not performing a full recursion test, at least check if we are in
+                // a simple recursion scenario to prevent stack overflow crashes
+                wxCHECK2_MSG( sheet->GetFileName() != aSheet->GetFileName(), continue,
+                              wxT( "Recursion prevented in SCH_SHEET_LIST::BuildSheetList" ) );
+
                 BuildSheetList( sheet, false );
             }
         }
diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp
index e89ddc5f2e..bfa11715a4 100644
--- a/eeschema/tools/sch_edit_tool.cpp
+++ b/eeschema/tools/sch_edit_tool.cpp
@@ -1408,6 +1408,21 @@ int SCH_EDIT_TOOL::RepeatDrawItem( const TOOL_EVENT& aEvent )
                                      schIUScale.MilsToIU( cfg->m_Drawing.default_repeat_offset_y ) ) );
         }
 
+        // If cloning a sheet, check that we aren't going to create recursion
+        if( newItem->Type() == SCH_SHEET_T )
+        {
+            SCH_SHEET_PATH* currentSheet = &m_frame->GetCurrentSheet();
+            SCH_SHEET* sheet = static_cast<SCH_SHEET*>( newItem );
+
+            if( m_frame->CheckSheetForRecursion( sheet, currentSheet ) )
+            {
+                // Clear out the filename so that the user can pick a new one
+                sheet->SetFileName( wxEmptyString );
+                sheet->GetScreen()->SetFileName( wxEmptyString );
+                restore_state = !m_frame->EditSheetProperties( sheet, currentSheet, nullptr );
+            }
+        }
+
         m_toolMgr->RunAction<EDA_ITEM*>( EE_ACTIONS::addItemToSel, newItem );
         newItem->SetFlags( IS_NEW );
         m_frame->AddToScreen( newItem, m_frame->GetScreen() );