mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-09 22:17:55 -05:00
GP-6183 fixed template shortening infinite loop issue
This commit is contained in:
@@ -1226,14 +1226,159 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
|||||||
public void createShortenedTemplateNamesForClasses(List<RecoveredClass> recoveredClasses)
|
public void createShortenedTemplateNamesForClasses(List<RecoveredClass> recoveredClasses)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
||||||
|
// update recovered classes variable that stores shortened names such that all templated
|
||||||
|
// class names get generic classname<...> shortened name to start with
|
||||||
|
// also create a map of all same classname<> templates separated into unique parent namespaces
|
||||||
|
// and the list of recovered class objects in that namespace with the same generic
|
||||||
|
// classname<...> shortened name
|
||||||
|
Map<String, Map<Namespace, List<RecoveredClass>>> templateClassesMap =
|
||||||
|
mapTemplateClasses(recoveredClasses);
|
||||||
|
|
||||||
|
// now loop through them to make sure all in a particular namespace have unique shortened
|
||||||
|
// names or if unable to do that, remove the shortened name and use the full template name
|
||||||
|
Set<String> shortenedNames = templateClassesMap.keySet();
|
||||||
|
for (String shortenedName : shortenedNames) {
|
||||||
|
|
||||||
|
monitor.checkCancelled();
|
||||||
|
|
||||||
|
Map<Namespace, List<RecoveredClass>> namespaceMap =
|
||||||
|
templateClassesMap.get(shortenedName);
|
||||||
|
for (Namespace parentNamespace : namespaceMap.keySet()) {
|
||||||
|
|
||||||
|
monitor.checkCancelled();
|
||||||
|
|
||||||
|
// if only one, keep empty template
|
||||||
|
List<RecoveredClass> sameNameClassesInNamespace = namespaceMap.get(parentNamespace);
|
||||||
|
if (sameNameClassesInNamespace.size() == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
processDuplicateTemplates(sameNameClassesInNamespace, shortenedName,
|
||||||
|
parentNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to create unique shortened names for those blank templates that are dupes in a
|
||||||
|
* particular namespace
|
||||||
|
* @param sameNameClassesInNamespace the list of same name dupes in the given namespace
|
||||||
|
* @param shortenedName the duplicated shortened name
|
||||||
|
* @throws CancelledException if cancelled
|
||||||
|
*/
|
||||||
|
private void processDuplicateTemplates(List<RecoveredClass> sameNameClassesInNamespace,
|
||||||
|
String shortenedName, Namespace parentNamespace) throws CancelledException {
|
||||||
|
|
||||||
|
// first verify that all are in the same parent namespace
|
||||||
|
for (RecoveredClass recoveredClass : sameNameClassesInNamespace) {
|
||||||
|
if (!recoveredClass.getClassNamespace().getParentNamespace().equals(parentNamespace)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"This method is meant to dedupe shortened class names in the same parent namespace");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RecoveredClass> classesToProcess =
|
||||||
|
new ArrayList<RecoveredClass>(sameNameClassesInNamespace);
|
||||||
|
|
||||||
|
// First, check for a simple internal to the template (ie just one item in it
|
||||||
|
// if that is the case then just keep the original name
|
||||||
|
for (RecoveredClass classWithSameShortName : sameNameClassesInNamespace) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
|
||||||
|
if (containsSimpleTemplate(classWithSameShortName.getName())) {
|
||||||
|
//reset shortened name variable to empty to indicate no shortened name
|
||||||
|
classWithSameShortName.addShortenedTemplatedName(new String());
|
||||||
|
classesToProcess.remove(classWithSameShortName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if none left after removing simple ones then continue processing next namespace
|
||||||
|
if (classesToProcess.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if only one left after removing the simple templates then use it with first part of
|
||||||
|
// template internal (ie up to the first comma)
|
||||||
|
if (classesToProcess.size() == 1) {
|
||||||
|
RecoveredClass classWithSameShortName = classesToProcess.get(0);
|
||||||
|
String newName = getNewShortenedTemplateName(classWithSameShortName, 1);
|
||||||
|
classWithSameShortName.addShortenedTemplatedName(newName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if more than one complex left over after all the removals above, then keep trying to
|
||||||
|
// get unique name
|
||||||
|
int commaIndex = 1;
|
||||||
|
while (!classesToProcess.isEmpty()) {
|
||||||
|
|
||||||
|
List<RecoveredClass> leftoversWithSameShortName =
|
||||||
|
new ArrayList<RecoveredClass>(classesToProcess);
|
||||||
|
|
||||||
|
// update these classes so their short names include up to the n'th comma
|
||||||
|
for (RecoveredClass currentClass : leftoversWithSameShortName) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
String newShortenedTemplateName =
|
||||||
|
getNewShortenedTemplateName(currentClass, commaIndex);
|
||||||
|
|
||||||
|
// check to see if the new name is equal to the original class name
|
||||||
|
// if so, remove the shortened name and just use full name for that class
|
||||||
|
// also remove from list to process
|
||||||
|
if (newShortenedTemplateName.equals(currentClass.getName())) {
|
||||||
|
currentClass.addShortenedTemplatedName(new String());
|
||||||
|
classesToProcess.remove(currentClass);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// else update with new shortened name
|
||||||
|
currentClass.addShortenedTemplatedName(newShortenedTemplateName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if only one left then we are done
|
||||||
|
if (classesToProcess.size() == 1) {
|
||||||
|
classesToProcess.remove(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise see if any are unique and if so remove from list
|
||||||
|
List<RecoveredClass> classesWithUpdatedNames =
|
||||||
|
new ArrayList<RecoveredClass>(classesToProcess);
|
||||||
|
|
||||||
|
for (RecoveredClass currentClass : classesWithUpdatedNames) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
|
||||||
|
String shortenedTemplateName = currentClass.getShortenedTemplateName();
|
||||||
|
|
||||||
|
List<RecoveredClass> classesWithSameShortName = getClassesWithSameShortenedName(
|
||||||
|
classesWithUpdatedNames, shortenedTemplateName);
|
||||||
|
|
||||||
|
if (classesWithSameShortName.size() == 1) {
|
||||||
|
classesToProcess.remove(classesWithSameShortName.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// at this point either the classesToProcess will be empty and we are done
|
||||||
|
// OR there are still some with same (now with more of the template internal included)
|
||||||
|
// name so update commaIndex so that on next pass the internal will add more text up
|
||||||
|
// to this new comma index and so on until all are unique or back to their original
|
||||||
|
// full template name
|
||||||
|
commaIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RecoveredClass> getClassesWithTemplateNames(List<RecoveredClass> recoveredClasses)
|
||||||
|
throws CancelledException {
|
||||||
|
|
||||||
List<RecoveredClass> classesWithTemplates = new ArrayList<RecoveredClass>();
|
List<RecoveredClass> classesWithTemplates = new ArrayList<RecoveredClass>();
|
||||||
|
|
||||||
// create list with only classes that have templates in name and add completely stripped
|
// create list with only classes that have templates in name and add completely stripped
|
||||||
// template name to class var
|
// template name to class var
|
||||||
Iterator<RecoveredClass> recoveredClassesIterator = recoveredClasses.iterator();
|
for (RecoveredClass recoveredClass : recoveredClasses) {
|
||||||
while (recoveredClassesIterator.hasNext()) {
|
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
RecoveredClass recoveredClass = recoveredClassesIterator.next();
|
|
||||||
|
if (!recoveredClass.getShortenedTemplateName().isEmpty()) {
|
||||||
|
classesWithTemplates.add(recoveredClass);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
String className = recoveredClass.getName();
|
String className = recoveredClass.getName();
|
||||||
|
|
||||||
@@ -1243,115 +1388,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
|||||||
classesWithTemplates.add(recoveredClass);
|
classesWithTemplates.add(recoveredClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return classesWithTemplates;
|
||||||
// iterate over map and remove entries that already have unique shortened names on map and
|
|
||||||
// add those unique names to class as shorted name
|
|
||||||
// for those with non-unique names, process them as a group of matched names
|
|
||||||
List<RecoveredClass> classesToProcess = new ArrayList<RecoveredClass>(classesWithTemplates);
|
|
||||||
|
|
||||||
Iterator<RecoveredClass> classWithTemplatesIterator = classesWithTemplates.iterator();
|
|
||||||
|
|
||||||
while (classWithTemplatesIterator.hasNext()) {
|
|
||||||
monitor.checkCancelled();
|
|
||||||
RecoveredClass currentClass = classWithTemplatesIterator.next();
|
|
||||||
|
|
||||||
// skip if already processed
|
|
||||||
if (!classesToProcess.contains(currentClass)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String currentShortenedName = currentClass.getShortenedTemplateName();
|
|
||||||
|
|
||||||
// if removing the middle of template results in unique name then keep that name and
|
|
||||||
// remove class from list to process
|
|
||||||
List<RecoveredClass> classesWithSameShortenedName =
|
|
||||||
getClassesWithSameShortenedName(classesToProcess, currentShortenedName);
|
|
||||||
|
|
||||||
if (classesWithSameShortenedName.size() == 1) {
|
|
||||||
classesToProcess.remove(currentClass);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<RecoveredClass> classesWithSameShortnameIterator =
|
|
||||||
classesWithSameShortenedName.iterator();
|
|
||||||
while (classesWithSameShortnameIterator.hasNext()) {
|
|
||||||
monitor.checkCancelled();
|
|
||||||
|
|
||||||
RecoveredClass classWithSameShortName = classesWithSameShortnameIterator.next();
|
|
||||||
|
|
||||||
// if removing the middle of template results in duplicate names then
|
|
||||||
// check for a simple internal to the template (ie just one item in it
|
|
||||||
// if that is the case then just keep the original name
|
|
||||||
if (containsSimpleTemplate(classWithSameShortName.getName())) {
|
|
||||||
classWithSameShortName.addShortenedTemplatedName(new String());
|
|
||||||
classesWithSameShortnameIterator.remove();
|
|
||||||
classesToProcess.remove(classWithSameShortName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if none left after removing simple ones then continue processing next class
|
|
||||||
if (classesWithSameShortenedName.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if only one left after removing the simple templates then use it with first part of
|
|
||||||
// template internal
|
|
||||||
if (classesWithSameShortenedName.size() == 1) {
|
|
||||||
RecoveredClass classWithSameShortName = classesWithSameShortenedName.get(0);
|
|
||||||
String newName = getNewShortenedTemplateName(classWithSameShortName, 1);
|
|
||||||
classWithSameShortName.addShortenedTemplatedName(newName);
|
|
||||||
classesToProcess.remove(classWithSameShortName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if more than one complex left over after all the removals above, then keep trying to
|
|
||||||
// get unique name
|
|
||||||
int commaIndex = 1;
|
|
||||||
while (!classesWithSameShortenedName.isEmpty()) {
|
|
||||||
|
|
||||||
List<RecoveredClass> leftoversWithSameShortName =
|
|
||||||
new ArrayList<RecoveredClass>(classesWithSameShortenedName);
|
|
||||||
|
|
||||||
// update all their shorted names to include up to the n'th comma
|
|
||||||
Iterator<RecoveredClass> leftoversIterator = leftoversWithSameShortName.iterator();
|
|
||||||
|
|
||||||
while (leftoversIterator.hasNext()) {
|
|
||||||
|
|
||||||
monitor.checkCancelled();
|
|
||||||
RecoveredClass currentClassWithSameShortName = leftoversIterator.next();
|
|
||||||
currentClassWithSameShortName.addShortenedTemplatedName(
|
|
||||||
getNewShortenedTemplateName(currentClassWithSameShortName, commaIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
// now iterate and see if any are unique and if so remove from list
|
|
||||||
// if not, add up to next comma and so on until all are unique
|
|
||||||
List<RecoveredClass> leftovers2WithSameShortName =
|
|
||||||
new ArrayList<RecoveredClass>(classesWithSameShortenedName);
|
|
||||||
Iterator<RecoveredClass> leftovers2Iterator =
|
|
||||||
leftovers2WithSameShortName.iterator();
|
|
||||||
|
|
||||||
while (leftovers2Iterator.hasNext()) {
|
|
||||||
|
|
||||||
monitor.checkCancelled();
|
|
||||||
RecoveredClass currentClassWithSameShortName = leftovers2Iterator.next();
|
|
||||||
|
|
||||||
String shortenedTemplateName =
|
|
||||||
currentClassWithSameShortName.getShortenedTemplateName();
|
|
||||||
|
|
||||||
List<RecoveredClass> classesWithSameShortName =
|
|
||||||
getClassesWithSameShortenedName(classesToProcess, shortenedTemplateName);
|
|
||||||
|
|
||||||
if (classesWithSameShortName.size() == 1) {
|
|
||||||
classesToProcess.remove(classesWithSameShortName.get(0));
|
|
||||||
classesWithSameShortenedName.remove(classesWithSameShortName.get(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
commaIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1372,7 +1409,7 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
|||||||
return nameWithoutTemplates;
|
return nameWithoutTemplates;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNewShortenedTemplateName(RecoveredClass recoveredClass, int commaIndex) {
|
private String getNewShortenedTemplateName(RecoveredClass recoveredClass, int commaIndex) {
|
||||||
|
|
||||||
String className = recoveredClass.getName();
|
String className = recoveredClass.getName();
|
||||||
|
|
||||||
@@ -1393,21 +1430,62 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
|||||||
return shortenedName;
|
return shortenedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RecoveredClass> getClassesWithSameShortenedName(
|
private Map<Namespace, List<RecoveredClass>> mapClassesWithSameShortenedName(
|
||||||
List<RecoveredClass> templateClasses, String shortenedName) throws CancelledException {
|
List<RecoveredClass> templateClasses, String shortenedName) throws CancelledException {
|
||||||
|
|
||||||
List<RecoveredClass> classesWithSameShortenedName = new ArrayList<RecoveredClass>();
|
Map<Namespace, List<RecoveredClass>> sameNamespaceMap = new HashMap<>();
|
||||||
|
|
||||||
Iterator<RecoveredClass> classIterator = templateClasses.iterator();
|
for (RecoveredClass currentClass : templateClasses) {
|
||||||
while (classIterator.hasNext()) {
|
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
RecoveredClass currentClass = classIterator.next();
|
|
||||||
|
|
||||||
if (currentClass.getShortenedTemplateName().equals(shortenedName)) {
|
if (currentClass.getShortenedTemplateName().equals(shortenedName)) {
|
||||||
classesWithSameShortenedName.add(currentClass);
|
Namespace parentNamespace = currentClass.getClassNamespace().getParentNamespace();
|
||||||
|
List<RecoveredClass> sameShortNameClasses = sameNamespaceMap.get(parentNamespace);
|
||||||
|
if (sameShortNameClasses == null) {
|
||||||
|
sameShortNameClasses = new ArrayList<>();
|
||||||
|
}
|
||||||
|
sameShortNameClasses.add(currentClass);
|
||||||
|
sameNamespaceMap.put(parentNamespace, sameShortNameClasses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return classesWithSameShortenedName;
|
return sameNamespaceMap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RecoveredClass> getClassesWithSameShortenedName(
|
||||||
|
List<RecoveredClass> templateClasses, String shortenedName) throws CancelledException {
|
||||||
|
|
||||||
|
List<RecoveredClass> sameShortNameClasses = new ArrayList<>();
|
||||||
|
|
||||||
|
for (RecoveredClass currentClass : templateClasses) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
if (currentClass.getShortenedTemplateName().equals(shortenedName)) {
|
||||||
|
|
||||||
|
sameShortNameClasses.add(currentClass);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sameShortNameClasses;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Map<Namespace, List<RecoveredClass>>> mapTemplateClasses(
|
||||||
|
List<RecoveredClass> recoveredClasses) throws CancelledException {
|
||||||
|
|
||||||
|
List<RecoveredClass> templateClasses = getClassesWithTemplateNames(recoveredClasses);
|
||||||
|
|
||||||
|
Map<String, Map<Namespace, List<RecoveredClass>>> sameNameMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (RecoveredClass currentClass : templateClasses) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
|
||||||
|
String shortenedName = currentClass.getShortenedTemplateName();
|
||||||
|
Map<Namespace, List<RecoveredClass>> sameShortNamesMap = sameNameMap.get(shortenedName);
|
||||||
|
if (sameShortNamesMap == null) {
|
||||||
|
sameNameMap.put(shortenedName,
|
||||||
|
mapClassesWithSameShortenedName(templateClasses, shortenedName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sameNameMap;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user