From 5295664364e3c577a46727686d3a5eb75c578aa5 Mon Sep 17 00:00:00 2001 From: Ryan Kurtz Date: Fri, 1 Apr 2022 16:57:52 -0400 Subject: [PATCH] GP-1733: Fixed an issue in the GhidraDev plugin that could cause old installed extensions to incorrectly remain after performing a "Link Ghidra" operation --- .../GhidraDevPlugin/.launch/GhidraDev.launch | 28 +++++----- .../GhidraDevPlugin/GhidraDev_README.html | 4 ++ .../utils/GhidraProjectUtils.java | 56 ++++++++++++++++--- 3 files changed, 65 insertions(+), 23 deletions(-) diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch index 402dcc2c55..d99a096da7 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/.launch/GhidraDev.launch @@ -154,21 +154,19 @@ + - - - @@ -181,7 +179,6 @@ - @@ -200,9 +197,9 @@ - - - + + + @@ -268,12 +265,18 @@ + + + + + + @@ -305,6 +308,8 @@ + + @@ -320,17 +325,12 @@ - - - - - - + @@ -397,7 +397,7 @@ - + diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html index f8d1ed4aaa..0ccba9ff87 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/GhidraDev_README.html @@ -58,6 +58,10 @@ change with future releases.

  • GhidraDev now requires Eclipse 2020-09 4.17 or later.
  • +
  • + Fixed an issue that could cause old extensions to incorrectly remain on the Ghidra project + classpath after performing a "Link Ghidra." +
  • 2.1.5: Eclipse Python breakpoints now work when Eclipse installs PyDev in .p2 bundle pool directory.

    diff --git a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraProjectUtils.java b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraProjectUtils.java index a73166c137..b65c0d752e 100644 --- a/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraProjectUtils.java +++ b/GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraProjectUtils.java @@ -32,6 +32,7 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.part.FileEditorInput; +import generic.jar.ResourceFile; import ghidra.GhidraApplicationLayout; import ghidra.framework.GModule; import ghidra.launch.JavaConfig; @@ -356,8 +357,8 @@ public class GhidraProjectUtils { // Get the project's existing linked Ghidra installation folder and path (it may not exist) IFolder ghidraFolder = javaProject.getProject().getFolder(GhidraProjectUtils.GHIDRA_FOLDER_NAME); - IPath oldGhidraInstallPath = ghidraFolder.exists() - ? new Path(ghidraFolder.getLocation().toFile().getAbsolutePath()) + GhidraApplicationLayout oldGhidraLayout = ghidraFolder.exists() + ? new GhidraApplicationLayout(ghidraFolder.getLocation().toFile()) : null; // Loop through the project's existing classpath to decide what to keep (things that aren't @@ -371,7 +372,7 @@ public class GhidraProjectUtils { // We'll decide whether or not to keep it later. if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER && entry.getPath().toString().startsWith(JavaRuntime.JRE_CONTAINER)) { - if (oldGhidraInstallPath == null) { + if (oldGhidraLayout == null) { vmEntryCandidate = entry; } } @@ -393,18 +394,22 @@ public class GhidraProjectUtils { entryFolder = ResourcesPlugin.getWorkspace().getRoot().getFolder(entry.getPath()); } if (entryFolder != null && entryFolder.isLinked() && - oldGhidraInstallPath != null && - oldGhidraInstallPath.isPrefixOf(entryFolder.getLocation())) { + inGhidraInstallation(oldGhidraLayout, entryFolder.getLocation())) { + String oldGhidraInstallPath = + oldGhidraLayout.getApplicationInstallationDir().getAbsolutePath(); String origPath = entryFolder.getLocation().toString(); String newPath = ghidraInstallDir.getAbsolutePath() + - origPath.substring(oldGhidraInstallPath.toString().length()); + origPath.substring(oldGhidraInstallPath.length()); entryFolder.createLink(new Path(newPath), IResource.REPLACE, monitor); classpathEntriesToKeep.add(JavaCore.newSourceEntry(entryFolder.getFullPath())); } - // If it's anything else that doesn't live in the old Ghidra installation, keep it. - else if (oldGhidraInstallPath == null || - !oldGhidraInstallPath.isPrefixOf(entry.getPath())) { + // If it's anything else that doesn't live in the old Ghidra installation, keep it. + // Note that installed Ghidra extensions can live in the user settings directory + // which is outside the installation directory. We don't want to keep these. + else if (!inGhidraInstallation(oldGhidraLayout, entry.getPath()) && + !isGhidraExtension(oldGhidraLayout, entry.getPath())) { classpathEntriesToKeep.add(entry); + ghidraLayout.getExtensionInstallationDirs(); } } } @@ -453,6 +458,39 @@ public class GhidraProjectUtils { } } + /** + * Checks to see if the given path is contained within the given Ghidra layout's installation + * directory. + * + * @param ghidraLayout A Ghidra layout that contains the installation directory to check. + * @param path The path to check. + * @return True if the given path is contained within the given Ghidra layout's installation + * directory. + */ + private static boolean inGhidraInstallation(GhidraApplicationLayout ghidraLayout, IPath path) { + return ghidraLayout != null && + new Path(ghidraLayout.getApplicationInstallationDir().getAbsolutePath()) + .isPrefixOf(path); + } + + /** + * Checks to see if the given path is a Ghidra extension. + * + * @param ghidraLayout A Ghidra layout that contains extension locations to check against. + * @param path The path to check. + * @return True if the given path is a Ghidra extension installed in the given Ghidra layout. + */ + private static boolean isGhidraExtension(GhidraApplicationLayout ghidraLayout, IPath path) { + if (ghidraLayout != null) { + for (ResourceFile extensionDir : ghidraLayout.getExtensionInstallationDirs()) { + if (new Path(extensionDir.getAbsolutePath()).isPrefixOf(path)) { + return true; + } + } + } + return false; + } + /** * Gets the appropriate classpath attribute for Ghidra's javadoc in the provided layout. *