diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java index 71339f1bc1..5e0c8e7441 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/actions/AutoVersionTrackingTask.java @@ -592,6 +592,15 @@ public class AutoVersionTrackingTask extends Task { continue; } + if (hasAcceptedRelatedAssociation(association, monitor)) { + Msg.warn(AutoVersionTrackingTask.class, + "This association has a related association with an accepted match so cannot " + + "make this association accepted which would try to block the already accepted " + + "related association " + + association); + continue; + } + if (!tryToSetAccepted(association)) { continue; } @@ -635,6 +644,44 @@ public class AutoVersionTrackingTask extends Task { } } + /** + * Method to test whether any related associations (ie associations with either the same source + * or the same destination address) have already been accepted + * @param association the given association (src/dest match pair) + * @param taskMonitor the task monitor + * @return true if any related associations have already been accepted, false otherwise + * @throws CancelledException if cancelled + */ + private boolean hasAcceptedRelatedAssociation(VTAssociation association, + TaskMonitor taskMonitor) throws CancelledException { + + VTAssociationManager vtAssocManager = session.getAssociationManager(); + + Set relatedAssociations = + new HashSet( + vtAssocManager.getRelatedAssociationsBySourceAndDestinationAddress( + association.getSourceAddress(), association.getDestinationAddress())); + + for (VTAssociation relatedAssociation : relatedAssociations) { + + taskMonitor.checkCancelled(); + + //skip self + if (relatedAssociation.equals(association)) { + continue; + } + + VTAssociationStatus status = relatedAssociation.getStatus(); + + if (status.equals(VTAssociationStatus.ACCEPTED)) { + Msg.debug(this, relatedAssociation.toString() + " is already accepted match."); + return true; + } + + } + return false; + } + /** * Method to accept matches and apply markup for duplicate function instruction matches with * matching operands if they are a unique match within their associated subset. To explain in @@ -1237,14 +1284,25 @@ public class AutoVersionTrackingTask extends Task { * @param match The match to try and accept and apply markup to * @param monitor Allow user to cancel * @return true if there are any markup errors, false if no markup errors + * @throws CancelledException if cancelled */ - private boolean tryToAcceptMatchAndApplyMarkup(VTMatch match, TaskMonitor monitor) { + private boolean tryToAcceptMatchAndApplyMarkup(VTMatch match, TaskMonitor monitor) + throws CancelledException { VTAssociation association = match.getAssociation(); // skip already accepted or blocked matches if (association.getStatus() == VTAssociationStatus.AVAILABLE) { + if (hasAcceptedRelatedAssociation(association, monitor)) { + Msg.warn(AutoVersionTrackingTask.class, + "This association has a related association with an accepted match so cannot " + + "make this association accepted which would try to block the already accepted " + + "related association " + + association); + return false; + } + // Try to accept the match if (tryToSetAccepted(association)) {