GP-1733: Fixed an issue in the GhidraDev plugin that could cause old

installed extensions to incorrectly remain after performing a "Link
Ghidra" operation
This commit is contained in:
Ryan Kurtz 2022-04-01 16:57:52 -04:00
parent 20dac11be6
commit 5295664364
3 changed files with 65 additions and 23 deletions

View File

@ -154,21 +154,19 @@
<setEntry value="org.python.pydev.feature:default"/>
</setAttribute>
<setAttribute key="selected_target_bundles">
<setEntry value="biz.aQute.bnd.util"/>
<setEntry value="biz.aQute.bndlib@default:default"/>
<setEntry value="ch.qos.logback.classic@default:default"/>
<setEntry value="ch.qos.logback.core@default:default"/>
<setEntry value="ch.qos.logback.slf4j@default:false"/>
<setEntry value="com.google.gson@default:default"/>
<setEntry value="com.google.guava*21.0.0.v20170206-1425@default:default"/>
<setEntry value="com.google.guava*27.1.0.v20190517-1946@default:default"/>
<setEntry value="com.google.guava*30.1.0.v20210127-2300@default:default"/>
<setEntry value="com.ibm.icu@default:default"/>
<setEntry value="com.python.pydev.analysis@default:default"/>
<setEntry value="com.python.pydev.debug@default:default"/>
<setEntry value="com.python.pydev.refactoring@default:default"/>
<setEntry value="com.sun.jna*4.5.1.v20190425-1842@default:default"/>
<setEntry value="com.sun.jna*5.8.0.v20210503-0343@default:default"/>
<setEntry value="com.sun.jna.platform*4.5.1.v20190425-1842@default:default"/>
<setEntry value="com.sun.jna.platform*5.8.0.v20210406-1004@default:default"/>
<setEntry value="jakarta.servlet-api@default:default"/>
<setEntry value="javax.annotation@default:default"/>
@ -181,7 +179,6 @@
<setEntry value="org.apache.commons.codec@default:default"/>
<setEntry value="org.apache.commons.io@default:default"/>
<setEntry value="org.apache.commons.jxpath@default:default"/>
<setEntry value="org.apache.commons.lang@default:default"/>
<setEntry value="org.apache.commons.logging@default:default"/>
<setEntry value="org.apache.felix.gogo.command@default:default"/>
<setEntry value="org.apache.felix.gogo.runtime@default:default"/>
@ -200,9 +197,9 @@
<setEntry value="org.eclipse.ant.core@default:default"/>
<setEntry value="org.eclipse.buildship.core@default:default"/>
<setEntry value="org.eclipse.buildship.ui@default:default"/>
<setEntry value="org.eclipse.cdt.core.native@default:default"/>
<setEntry value="org.eclipse.cdt.core.win32.x86_64@default:false"/>
<setEntry value="org.eclipse.cdt.core.win32@default:false"/>
<setEntry value="org.eclipse.cdt.core.native*5.7.0.201502131403@default:default"/>
<setEntry value="org.eclipse.cdt.core.win32*5.4.0.201502131403@default:default"/>
<setEntry value="org.eclipse.cdt.core.win32.x86_64*5.3.0.201502131403@default:default"/>
<setEntry value="org.eclipse.cdt.core@default:default"/>
<setEntry value="org.eclipse.cdt.ui@default:default"/>
<setEntry value="org.eclipse.compare.core@default:default"/>
@ -268,12 +265,18 @@
<setEntry value="org.eclipse.equinox.p2.artifact.repository@default:default"/>
<setEntry value="org.eclipse.equinox.p2.core@default:default"/>
<setEntry value="org.eclipse.equinox.p2.director@default:default"/>
<setEntry value="org.eclipse.equinox.p2.directorywatcher"/>
<setEntry value="org.eclipse.equinox.p2.engine@default:default"/>
<setEntry value="org.eclipse.equinox.p2.extensionlocation@default:default"/>
<setEntry value="org.eclipse.equinox.p2.garbagecollector"/>
<setEntry value="org.eclipse.equinox.p2.jarprocessor@default:default"/>
<setEntry value="org.eclipse.equinox.p2.metadata.repository@default:default"/>
<setEntry value="org.eclipse.equinox.p2.metadata@default:default"/>
<setEntry value="org.eclipse.equinox.p2.operations@default:default"/>
<setEntry value="org.eclipse.equinox.p2.publisher"/>
<setEntry value="org.eclipse.equinox.p2.publisher.eclipse"/>
<setEntry value="org.eclipse.equinox.p2.repository@default:default"/>
<setEntry value="org.eclipse.equinox.p2.touchpoint.eclipse"/>
<setEntry value="org.eclipse.equinox.p2.ui@default:default"/>
<setEntry value="org.eclipse.equinox.preferences@default:default"/>
<setEntry value="org.eclipse.equinox.registry@default:default"/>
@ -305,6 +308,8 @@
<setEntry value="org.eclipse.jetty.servlet@default:default"/>
<setEntry value="org.eclipse.jetty.util.ajax@default:default"/>
<setEntry value="org.eclipse.jetty.util@default:default"/>
<setEntry value="org.eclipse.jetty.webapp"/>
<setEntry value="org.eclipse.jetty.xml"/>
<setEntry value="org.eclipse.jface.databinding@default:default"/>
<setEntry value="org.eclipse.jface.notifications@default:default"/>
<setEntry value="org.eclipse.jface.text@default:default"/>
@ -320,17 +325,12 @@
<setEntry value="org.eclipse.m2e.maven.runtime@default:default"/>
<setEntry value="org.eclipse.m2e.model.edit@default:default"/>
<setEntry value="org.eclipse.m2e.workspace.cli@default:default"/>
<setEntry value="org.eclipse.mylyn.commons.core@default:default"/>
<setEntry value="org.eclipse.mylyn.commons.notifications.core@default:default"/>
<setEntry value="org.eclipse.mylyn.commons.notifications.ui@default:default"/>
<setEntry value="org.eclipse.mylyn.commons.screenshots@default:default"/>
<setEntry value="org.eclipse.mylyn.commons.ui@default:default"/>
<setEntry value="org.eclipse.mylyn.commons.workbench@default:default"/>
<setEntry value="org.eclipse.osgi.compatibility.state@default:false"/>
<setEntry value="org.eclipse.osgi.services@default:default"/>
<setEntry value="org.eclipse.osgi.util@default:default"/>
<setEntry value="org.eclipse.osgi@-1:true"/>
<setEntry value="org.eclipse.platform@default:default"/>
<setEntry value="org.eclipse.rap.tools.launch.rwt"/>
<setEntry value="org.eclipse.search@default:default"/>
<setEntry value="org.eclipse.swt.win32.win32.x86_64@default:false"/>
<setEntry value="org.eclipse.swt@default:default"/>
@ -397,7 +397,7 @@
<setAttribute key="selected_workspace_bundles">
<setEntry value="ghidra.ghidradev@default:default"/>
</setAttribute>
<booleanAttribute key="show_selected_only" value="true"/>
<booleanAttribute key="show_selected_only" value="false"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfig" value="true"/>

View File

@ -58,6 +58,10 @@ change with future releases.</p>
<li>
GhidraDev now requires Eclipse 2020-09 4.17 or later.
</li>
<li>
Fixed an issue that could cause old extensions to incorrectly remain on the Ghidra project
classpath after performing a "Link Ghidra."
</li>
</ul>
<p><u><b>2.1.5</b>:</u> Eclipse Python breakpoints now work when Eclipse installs PyDev in .p2
bundle pool directory.</p>

View File

@ -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.
*