Don't allow a SaveAs to overwrite the root sheet.

Also prevents EESchema from loading sheets which recurse.

Fixes https://gitlab.com/kicad/code/kicad/issues/10872
This commit is contained in:
Jeff Young 2022-09-08 23:17:41 +01:00
parent 9626f0b66c
commit d030f03844
3 changed files with 47 additions and 7 deletions

View File

@ -417,7 +417,21 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aProje
ext == KiCadSchematicFileExtension + BackupFileSuffix )
{
if( destFile.GetName() == aProjectName )
{
destFile.SetName( aNewProjectName );
}
else if( destFile.GetName() == aNewProjectName )
{
wxString msg;
if( !aErrors.empty() )
aErrors += "\n";
msg.Printf( _( "Cannot copy file '%s' as it will be overwritten by the new root "
"sheet file." ), destFile.GetFullPath() );
aErrors += msg;
return;
}
// Sheet paths when auto-generated are relative to the root, so those will stay
// pointing to whatever they were pointing at.

View File

@ -149,7 +149,7 @@ SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
newSheet->SetFileName( relPath.GetFullPath() );
m_rootSheet = newSheet.get();
loadHierarchy( newSheet.get() );
loadHierarchy( SCH_SHEET_PATH(), newSheet.get() );
// If we got here, the schematic loaded successfully.
sheet = newSheet.release();
@ -160,7 +160,7 @@ SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
wxCHECK_MSG( aSchematic->IsValid(), nullptr, "Can't append to a schematic with no root!" );
m_rootSheet = &aSchematic->Root();
sheet = aAppendToMe;
loadHierarchy( sheet );
loadHierarchy( SCH_SHEET_PATH(), sheet );
}
wxASSERT( m_currentPath.size() == 1 ); // only the project path should remain
@ -173,7 +173,7 @@ SCH_SHEET* SCH_SEXPR_PLUGIN::Load( const wxString& aFileName, SCHEMATIC* aSchema
// Everything below this comment is recursive. Modify with care.
void SCH_SEXPR_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
void SCH_SEXPR_PLUGIN::loadHierarchy( const SCH_SHEET_PATH& aParentSheetPath, SCH_SHEET* aSheet )
{
SCH_SCREEN* screen = nullptr;
@ -195,7 +195,30 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
wxLogTrace( traceSchLegacyPlugin, "Current path '%s'", m_currentPath.top() );
wxLogTrace( traceSchLegacyPlugin, "Loading '%s'", fileName.GetFullPath() );
m_rootSheet->SearchHierarchy( fileName.GetFullPath(), &screen );
SCH_SHEET_PATH ancestorSheetPath = aParentSheetPath;
while( !ancestorSheetPath.empty() )
{
if( ancestorSheetPath.LastScreen()->GetFileName() == fileName.GetFullPath() )
{
if( !m_error.IsEmpty() )
m_error += "\n";
m_error += wxString::Format( _( "Could not load sheet '%s' because it already "
"appears as a direct ancestor in the schematic "
"hierarchy." ),
fileName.GetFullPath() );
fileName = wxEmptyString;
break;
}
ancestorSheetPath.pop_back();
}
if( ancestorSheetPath.empty() )
m_rootSheet->SearchHierarchy( fileName.GetFullPath(), &screen );
if( screen )
{
@ -236,7 +259,10 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
aSheet->GetScreen()->SetFileExists( false );
}
// This was moved out of the try{} block so that any sheets definitionsthat
SCH_SHEET_PATH currentSheetPath = aParentSheetPath;
currentSheetPath.push_back( aSheet );
// This was moved out of the try{} block so that any sheet definitions that
// the plugin fully parsed before the exception was raised will be loaded.
for( SCH_ITEM* aItem : aSheet->GetScreen()->Items().OfType( SCH_SHEET_T ) )
{
@ -244,7 +270,7 @@ void SCH_SEXPR_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
// Recursion starts here.
loadHierarchy( sheet );
loadHierarchy( currentSheetPath, sheet );
}
}

View File

@ -143,7 +143,7 @@ public:
static void FormatLibSymbol( LIB_SYMBOL* aPart, OUTPUTFORMATTER& aFormatter );
private:
void loadHierarchy( SCH_SHEET* aSheet );
void loadHierarchy( const SCH_SHEET_PATH& aParentSheetPath, SCH_SHEET* aSheet );
void loadFile( const wxString& aFileName, SCH_SHEET* aSheet );
void saveSymbol( SCH_SYMBOL* aSymbol, SCH_SHEET_PATH* aSheetPath, int aNestLevel,