mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-08-18 05:47:55 +08:00
GP-6691 - Find Uses of - Fixed flaws in finding structure field uses in the DataTypeReference API
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -94,7 +94,7 @@ public class FieldMatcher {
|
||||
}
|
||||
return dataType.getName() + " at " + fieldOffsets.toString();
|
||||
}
|
||||
return dataType.getName();
|
||||
return dataType.getName() + " <matches all fields>";
|
||||
}
|
||||
|
||||
private String generateCompositeFieldNameByOffset() {
|
||||
|
||||
+26
-8
@@ -17,12 +17,15 @@ package ghidra.app.extension.datatype.finder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import docking.widgets.search.SearchLocationContext;
|
||||
import ghidra.app.decompiler.ClangFieldToken;
|
||||
import ghidra.app.decompiler.ClangLine;
|
||||
import ghidra.app.services.DataTypeReference;
|
||||
import ghidra.app.services.FieldMatcher;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.Composite;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.Function;
|
||||
|
||||
/**
|
||||
* This class represents the use of a field of a {@link Composite} data type <b>where there is no
|
||||
@@ -84,12 +87,18 @@ public class AnonymousVariableAccessDR extends VariableAccessDR {
|
||||
// referring to the field and not the composite.
|
||||
//
|
||||
if (fieldMatcher.isIgnored()) {
|
||||
|
||||
if (matchesFieldType) {
|
||||
// no field name and the search type matches this reference's field type
|
||||
String fieldName = variable.getName();
|
||||
results.add(createReference(variable, fieldName));
|
||||
// no field to match and the search type matches this composite's field type
|
||||
String fieldName = null;
|
||||
DataTypeReference ref = createReferenceToVariable(variable, fieldName);
|
||||
results.add(ref);
|
||||
}
|
||||
// else there is no field and the search type does not match the reference's type
|
||||
|
||||
// else there is no field to match and the search type matched the composite type; as
|
||||
// mentioned in the comment above, we are ignoring the match on the composite, as
|
||||
// that is handled by the VariableAccessDR, which gets created before this object as the
|
||||
// tokens are being parsed.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -99,11 +108,20 @@ public class AnonymousVariableAccessDR extends VariableAccessDR {
|
||||
// The client has requested a particular field of the parent composite. We only have a
|
||||
// match if the parent type matches and the field name/offset matches.
|
||||
//
|
||||
String text = field.getText();
|
||||
String fieldName = field.getText();
|
||||
int offset = field.getOffset();
|
||||
if (matchesCompositeType && fieldMatcher.matches(text, offset)) {
|
||||
results.add(new DataTypeReference(compositeType, fieldMatcher.getFieldName(),
|
||||
getFunction(), getAddress(), getContext()));
|
||||
if (!fieldMatcher.matches(fieldName, offset)) {
|
||||
return; // the field does not match
|
||||
}
|
||||
|
||||
if (matchesCompositeType) {
|
||||
Function function = getFunction();
|
||||
Address address = getAddress();
|
||||
SearchLocationContext context = getContext();
|
||||
results.add(
|
||||
new DataTypeReference(compositeType, fieldName, function, address, context));
|
||||
}
|
||||
// else, matches the composite's field type, but not the parent type; this fails the
|
||||
// requirement that the composite type must match when searching for a field
|
||||
}
|
||||
}
|
||||
|
||||
+35
-8
@@ -478,8 +478,12 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
||||
DtrfDbg.println(function,
|
||||
"\tcreating an anonymous variable access: " + line);
|
||||
|
||||
// this can happen when a field is used anonymously, such as directly
|
||||
// after a nested array index operation
|
||||
// This can happen when a field is used anonymously, such as directly
|
||||
// after a nested array index operation. 'anonymous' here means that there
|
||||
// is no named variable in the decompiler that is being dereferenced. In
|
||||
// addition to seeing this for array accesses, we will also see this for
|
||||
// nested composite access, like foo->bar->baz. 'baz' is being accessed
|
||||
// anonymously.
|
||||
results.add(new AnonymousVariableAccessDR(line, field));
|
||||
continue;
|
||||
}
|
||||
@@ -497,15 +501,38 @@ public class DecompilerDataTypeReferenceFinder implements DataTypeReferenceFinde
|
||||
return false; // should not happen
|
||||
}
|
||||
|
||||
/*
|
||||
Unusual Code: The data type of 'field' is usually the parent structure that contains
|
||||
the field (not always though?). Also, apparently sometimes the data type of the
|
||||
'variable' in 'access' is that of the field being accessed instead of the parent
|
||||
structure. I'm guessing these conditions are bugs. Normally, the data type of
|
||||
'variable' should be the parent containing type and the data type of 'field' should
|
||||
be contained in the parent type.
|
||||
|
||||
This is used to determine when parent->child relationship is not correct so that we
|
||||
can create an special access type to represent that.
|
||||
*/
|
||||
|
||||
DataType parentType = field.getDataType();
|
||||
DataType variableType = variable.getDataType();
|
||||
if (DecompilerReference.isEqual(parentType, variableType)) {
|
||||
return false; // the types match; this is the normal flow
|
||||
}
|
||||
|
||||
// Note: the field's type is that of the parent structure, not the field. We want the
|
||||
// field's type, so we must retrieve that.
|
||||
DataType fieldDt = DecompilerReference.getFieldDataType(field);
|
||||
DataType fieldType = DecompilerReference.getFieldDataType(field);
|
||||
|
||||
// check for the unusual case where the 'variable' type may be that of the field
|
||||
if (DecompilerReference.isEqual(variableType, fieldType)) {
|
||||
|
||||
// Note: it would be nice to find a case(s) to verify this path
|
||||
|
||||
return false; // the types match; this is the normal flow
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// unusual code: getDataType() on the variable may return the type of the field being
|
||||
// accessed. Contrastingly, getDataType() on the field may return the
|
||||
// type of the parent structure.
|
||||
DataType variableDt = variable.getDataType();
|
||||
return !DecompilerReference.isEqual(variableDt, fieldDt);
|
||||
}
|
||||
|
||||
private VariableAccessDR getLastAccess(List<DecompilerReference> variables) {
|
||||
|
||||
+1
-2
@@ -88,8 +88,7 @@ public abstract class DecompilerReference {
|
||||
}
|
||||
|
||||
protected SearchLocationContext getContext() {
|
||||
SearchLocationContext context = getContext(variable);
|
||||
return context;
|
||||
return getContext(variable);
|
||||
}
|
||||
|
||||
protected SearchLocationContext getContext(DecompilerVariable var) {
|
||||
|
||||
+328
-96
File diff suppressed because it is too large
Load Diff
+1
@@ -78,4 +78,5 @@ public abstract class VariableDR extends DecompilerReference {
|
||||
results.add(new DataTypeReference(dataType, fieldName, function, address, context));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user