Merge remote-tracking branch 'origin/GP-4402_ghidra1_InvalidAddressRanges'

This commit is contained in:
Ryan Kurtz 2024-03-08 08:57:56 -05:00
commit cba4f432c7
15 changed files with 110 additions and 133 deletions

View file

@ -17,8 +17,7 @@ package ghidra.program.database;
import java.io.IOException;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.address.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -44,8 +43,8 @@ public interface ManagerDB {
* @throws IOException if a database io error occurs.
* @throws CancelledException if the user cancelled the operation via the task monitor.
*/
void programReady(int openMode, int currentRevision, TaskMonitor monitor) throws IOException,
CancelledException;
void programReady(int openMode, int currentRevision, TaskMonitor monitor)
throws IOException, CancelledException;
/**
* Clears all data caches.
@ -59,6 +58,9 @@ public interface ManagerDB {
/**
* Delete all objects which have been applied to the address range startAddr to endAddr
* and update the database accordingly.
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
*
* @param startAddr the first address in the range.
* @param endAddr the last address in the range.
* @param monitor the task monitor to use in any upgrade operations.
@ -69,6 +71,7 @@ public interface ManagerDB {
/**
* Move all objects within an address range to a new location.
*
* @param fromAddr the first address of the range to be moved.
* @param toAddr the address where to the range is to be moved.
* @param length the number of addresses to move.

View file

@ -724,6 +724,8 @@ public class CodeManager implements ErrorHandler, ManagerDB {
public void deleteAddressRange(Address start, Address end, TaskMonitor monitor)
throws CancelledException {
AddressRange.checkValidRange(start, end);
// Expand range to include any overlapping or delay-slotted instructions
CodeUnit cu = getCodeUnitContaining(start);
if (cu != null) {
@ -2194,11 +2196,14 @@ public class CodeManager implements ErrorHandler, ManagerDB {
/**
* Clears all comments in the given range (inclusive).
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
*
* @param start the start address of the range to clear
* @param end the end address of the range to clear
*/
public void clearComments(Address start, Address end) {
AddressRange.checkValidRange(start, end);
lock.acquire();
try {
try {
@ -2227,6 +2232,8 @@ public class CodeManager implements ErrorHandler, ManagerDB {
/**
* Clears the properties in the given range (inclusive).
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
*
* @param start the start address of the range to clear
* @param end the end address of the range to clear
@ -2289,6 +2296,9 @@ public class CodeManager implements ErrorHandler, ManagerDB {
/**
* Remove code units, symbols, equates, and references to code units in the given range
* (inclusive). Comments and comment history will be retained.
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
*
* @param start the start address of the range to clear
* @param end the end address of the range to clear
* @param clearContext if true all context-register values will be cleared over range
@ -2297,6 +2307,7 @@ public class CodeManager implements ErrorHandler, ManagerDB {
*/
public void clearCodeUnits(Address start, Address end, boolean clearContext,
TaskMonitor monitor) throws CancelledException {
AddressRange.checkValidRange(start, end);
lock.acquire();
try {
// Expand range to include any overlapping or delay-slotted instructions
@ -2336,10 +2347,10 @@ public class CodeManager implements ErrorHandler, ManagerDB {
* @param monitor the task monitor
*/
public void clearAll(boolean clearContext, TaskMonitor monitor) {
Address minAddr = program.getMinAddress();
Address maxAddr = program.getMaxAddress();
try {
clearCodeUnits(minAddr, maxAddr, clearContext, monitor);
for (AddressRange range : program.getMemory().getAddressRanges()) {
clearCodeUnits(range.getMinAddress(), range.getMaxAddress(), clearContext, monitor);
}
}
catch (CancelledException e) {
// nothing to do
@ -2571,17 +2582,18 @@ public class CodeManager implements ErrorHandler, ManagerDB {
}
/**
* Check if any instruction intersects the specified address range
* Check if any instruction intersects the specified address range.
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
*
* @param start start of range
* @param end end of range
* @throws ContextChangeException if there is a context register change conflict
*/
public void checkContextWrite(Address start, Address end) throws ContextChangeException {
AddressRange.checkValidRange(start, end);
lock.acquire();
try {
if (!start.getAddressSpace().equals(end.getAddressSpace())) {
throw new IllegalArgumentException();
}
if (!contextLockingEnabled || creatingInstruction ||
!program.getMemory().contains(start, end)) {
return;

View file

@ -22,8 +22,7 @@ import db.*;
import db.util.ErrorHandler;
import ghidra.docking.settings.SettingsDefinition;
import ghidra.program.database.map.AddressMap;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.KeyRange;
import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Data;
import ghidra.util.Lock;
@ -66,12 +65,12 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB
super(handle, addrMap, openMode, tablePrefix, errHandler, lock, monitor);
}
@Override
protected void initializeOtherAdapters(int openMode, TaskMonitor monitor)
throws CancelledException, IOException, VersionException {
if (addrMap != null) {
instanceSettingsAdapter =
SettingsDBAdapter.getAdapter(tablePrefix + INSTANCE_SETTINGS_TABLE_NAME, dbHandle,
openMode, addrMap, monitor);
instanceSettingsAdapter = SettingsDBAdapter.getAdapter(
tablePrefix + INSTANCE_SETTINGS_TABLE_NAME, dbHandle, openMode, addrMap, monitor);
}
}
@ -97,8 +96,7 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB
abstract protected void dataSettingChanged(Address address);
@Override
public boolean isChangeAllowed(Data data,
SettingsDefinition settingsDefinition) {
public boolean isChangeAllowed(Data data, SettingsDefinition settingsDefinition) {
if (settingsDefinition instanceof TypeDefSettingsDefinition) {
return false;
}
@ -261,8 +259,7 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB
monitor.checkCancelled();
DBRecord rec = iter.next();
// update address key (i.e., settings association ID) and re-introduce into table
Address addr = addrMap
.decodeAddress(
Address addr = addrMap.decodeAddress(
rec.getLongValue(SettingsDBAdapter.SETTINGS_ASSOCIATION_ID_COL));
long offset = addr.subtract(fromAddr);
addr = toAddr.add(offset);
@ -410,6 +407,7 @@ public abstract class ProgramBasedDataTypeManagerDB extends DataTypeManagerDB
if (instanceSettingsAdapter == null) {
throw new UnsupportedOperationException();
}
AddressRange.checkValidRange(startAddr, endAddr);
lock.acquire();
try {
List<?> addrKeyRanges = addrMap.getKeyRanges(startAddr, endAddr, false);

View file

@ -98,9 +98,7 @@ public class TreeManager implements ManagerDB {
public void imageBaseChanged(boolean commit) {
lock.acquire();
try {
Iterator<ModuleManager> iter = treeMap.values().iterator();
while (iter.hasNext()) {
ModuleManager m = iter.next();
for (ModuleManager m : treeMap.values()) {
m.imageBaseChanged(commit);
}
}
@ -376,6 +374,7 @@ public class TreeManager implements ManagerDB {
@Override
public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
throws CancelledException {
AddressRange.checkValidRange(startAddr, endAddr);
lock.acquire();
try {
Iterator<String> keys = treeMap.keySet().iterator();

View file

@ -28,6 +28,7 @@ import ghidra.program.database.ProgramDB;
import ghidra.program.database.bookmark.OldBookmark;
import ghidra.program.database.map.AddressMap;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.listing.BookmarkManager;
import ghidra.program.model.util.*;
import ghidra.program.util.ChangeManager;
@ -576,9 +577,7 @@ public class DBPropertyMapManager implements PropertyMapManager, ManagerDB {
public void removeAll(Address addr) {
lock.acquire();
try {
Iterator<PropertyMapDB<?>> iter = propertyMapCache.values().iterator();
while (iter.hasNext()) {
PropertyMapDB<?> pm = iter.next();
for (PropertyMapDB<?> pm : propertyMapCache.values()) {
pm.remove(addr);
}
@ -591,15 +590,13 @@ public class DBPropertyMapManager implements PropertyMapManager, ManagerDB {
@Override
public void removeAll(Address startAddr, Address endAddr, TaskMonitor monitor)
throws CancelledException {
AddressRange.checkValidRange(startAddr, endAddr);
lock.acquire();
try {
Iterator<PropertyMapDB<?>> iter = propertyMapCache.values().iterator();
while (iter.hasNext()) {
for (PropertyMapDB<?> pm : propertyMapCache.values()) {
monitor.checkCancelled();
PropertyMapDB<?> pm = iter.next();
pm.removeRange(startAddr, endAddr);
}
}
finally {
lock.release();
@ -611,13 +608,10 @@ public class DBPropertyMapManager implements PropertyMapManager, ManagerDB {
throws CancelledException {
lock.acquire();
try {
Iterator<PropertyMapDB<?>> iter = propertyMapCache.values().iterator();
while (iter.hasNext()) {
for (PropertyMapDB<?> pm : propertyMapCache.values()) {
monitor.checkCancelled();
PropertyMapDB<?> pm = iter.next();
pm.moveRange(fromAddr, fromAddr.add(length - 1), toAddr);
}
}
finally {
lock.release();

View file

@ -210,6 +210,7 @@ public class ProgramRegisterContextDB extends AbstractStoredProgramContext imple
@Override
public void deleteAddressRange(Address start, Address end, TaskMonitor monitor) {
AddressRange.checkValidRange(start, end);
lock.acquire();
try {
super.deleteAddressRange(start, end, monitor);

View file

@ -312,6 +312,7 @@ public class EquateManager implements EquateTable, ErrorHandler, ManagerDB {
@Override
public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
throws CancelledException {
AddressRange.checkValidRange(startAddr, endAddr);
lock.acquire();
try {
ArrayList<EquateRefDB> list = new ArrayList<>();

View file

@ -2427,6 +2427,7 @@ public class SymbolManager implements SymbolTable, ManagerDB {
@Override
public void deleteAddressRange(Address startAddr, Address endAddr, TaskMonitor monitor)
throws CancelledException {
AddressRange.checkValidRange(startAddr, endAddr);
lock.acquire();
try {
invalidateCache(true);

View file

@ -214,13 +214,7 @@ public class AddressRangeMapDB implements DBListener {
* @throws IllegalArgumentException if the end address is greater then the start address
*/
public void paintRange(Address startAddress, Address endAddress, Field value) {
if (!startAddress.hasSameAddressSpace(endAddress)) {
throw new IllegalArgumentException("Addresses must be in the same space!");
}
if (startAddress.compareTo(endAddress) > 0) {
throw new IllegalArgumentException("Start address must be <= end address!");
}
AddressRange.checkValidRange(startAddress, endAddress);
lock.acquire();
try {
clearCache();
@ -566,8 +560,7 @@ public class AddressRangeMapDB implements DBListener {
record = getRecordAfter(address);
if (record != null) {
Address startAddress = getStartAddress(record);
if (startAddress.hasSameAddressSpace(address) &&
startAddress.compareTo(address) > 0) {
if (startAddress.hasSameAddressSpace(address) && startAddress.compareTo(address) > 0) {
gapEnd = startAddress.subtract(1);
}
}

View file

@ -101,4 +101,25 @@ public interface AddressRange extends Comparable<AddressRange>, Iterable<Address
*/
public AddressSpace getAddressSpace();
/**
* Change the specified start and end addresses to see if they form a valid
* range within the same {@link AddressSpace}.
* @param start range start address
* @param end range end address
*/
public static void checkValidRange(Address start, Address end) {
if (start == null || end == null) {
throw new IllegalArgumentException("Null start or end address was specified");
}
if (!start.getAddressSpace().equals(end.getAddressSpace())) {
throw new IllegalArgumentException(
"Start and end addresses must be in same address space! Start " + start +
" end = " + end);
}
if (start.compareTo(end) > 0) {
throw new IllegalArgumentException("Start address must be less than or equal to " +
"end address: Start " + start + " end = " + end);
}
}
}

View file

@ -39,16 +39,6 @@ public class AddressSet implements AddressSetView {
public AddressSet() {
}
/**
* Create a new empty Address Set.
* @param factory NOT USED.
* @deprecated use {@link #AddressSet()} (will be kept until at least Ghidra 6.2)
*/
@Deprecated
public AddressSet(AddressFactory factory) {
this();
}
/**
* Create a new Address Set from an address range.
* @param range the range of addresses to include in this set.
@ -57,19 +47,11 @@ public class AddressSet implements AddressSetView {
add(range);
}
/**
* Create a new Address Set from an address range.
* @param factory NOT USED.
* @param range the range of addresses to include in this set.
* @deprecated use {@link #AddressSet(AddressRange)} (will be kept until at least Ghidra 6.2)
*/
@Deprecated
public AddressSet(AddressFactory factory, AddressRange range) {
add(range);
}
/**
* Creates a new Address set containing a single range
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
*
* @param start the start address of the range
* @param end the end address of the range
* @throws IllegalArgumentException if the start and end addresses are in different spaces. To
@ -80,19 +62,11 @@ public class AddressSet implements AddressSetView {
}
/**
* Creates a new Address set containing a single range
* @param start the start address of the range
* @param end the end address of the range
* @param factory NOT USED.
* @deprecated use {@link #AddressSet(Address, Address)} (will be kept until at least Ghidra 6.2)
*/
@Deprecated
public AddressSet(AddressFactory factory, Address start, Address end) {
addRange(start, end);
}
/**
* Creates a new Address set containing a single range
* Creates a new Address set containing a single range.
* Use of this method is generally discouraged since the set of addresses between a start and
* end address not contained within the same {@link AddressSpace} may be contain unexpected
* memory regions.
*
* @param start the start address of the range
* @param end the end address of the range
* @param program the program whose AddressFactory is used to resolve address ranges where the
@ -104,17 +78,6 @@ public class AddressSet implements AddressSetView {
addRange(program, start, end);
}
/**
* Create a new Address Set from an existing Address Set.
* @param set Existing Address Set to clone.
* @param factory NOT USED.
* @deprecated use {@link #AddressSet(AddressSetView)} (will be kept until at least Ghidra 6.2)
*/
@Deprecated
public AddressSet(AddressFactory factory, AddressSetView set) {
add(set);
}
/**
* Create a new Address Set from an existing Address Set.
* @param set Existing Address Set to clone.
@ -123,17 +86,6 @@ public class AddressSet implements AddressSetView {
add(set);
}
/**
* Create a new Address containing a single address.
* @param addr the address to be included in this address set.
* @param factory NOT USED.
* @deprecated use {@link #AddressSet(Address)} (will be kept until at least Ghidra 6.2)
*/
@Deprecated
public AddressSet(AddressFactory factory, Address addr) {
this(addr, addr);
}
/**
* Create a new Address containing a single address.
* @param addr the address to be included in this address set.
@ -167,7 +119,7 @@ public class AddressSet implements AddressSetView {
* @param end the end address of the range to add
*/
public void add(Address start, Address end) {
checkValidRange(start, end);
AddressRange.checkValidRange(start, end);
if (lastNode != null && !lastNode.isDisposed()) {
Address value = lastNode.getValue();
@ -422,6 +374,8 @@ public class AddressSet implements AddressSetView {
@Override
public final boolean contains(Address start, Address end) {
AddressRange.checkValidRange(start, end);
// See if there is a tree node whose range encapsulates the given range.
RedBlackEntry<Address, Address> entry = rbTree.getEntryLessThanEqual(start);
if (entry == null) {
@ -1136,10 +1090,6 @@ public class AddressSet implements AddressSetView {
return newSet;
}
private AddressRange getRange(RedBlackEntry<Address, Address> entry) {
return new AddressRangeImpl(entry.getKey(), entry.getValue());
}
private boolean contains(RedBlackEntry<Address, Address> entry, Address start) {
return entry.getKey().compareTo(start) <= 0 && entry.getValue().compareTo(start) >= 0;
}
@ -1193,23 +1143,6 @@ public class AddressSet implements AddressSetView {
}
private void checkValidRange(Address start, Address end) {
if (start == null || end == null) {
throw new IllegalArgumentException("Attempted to add a null address to this set.");
}
if (start.compareTo(end) > 0) {
throw new IllegalArgumentException("Start address must be less than or equal to " +
"end address: Start " + start + " end = " + end);
}
if (!start.getAddressSpace().equals(end.getAddressSpace())) {
throw new IllegalArgumentException(
"Start and end addresses must be in same address space! Start " + start +
" end = " + end);
}
}
private RedBlackEntry<Address, Address> createRangeNode(Address start, Address end) {
RedBlackEntry<Address, Address> newEntry = rbTree.getOrCreateEntry(start);
newEntry.setValue(end);

View file

@ -33,6 +33,8 @@ public interface AddressSetView extends Iterable<AddressRange> {
/**
* Test if the given address range is contained in this set.
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
* <P>
* @param start the first address in the range.
* @param end the last address in the range.
@ -56,11 +58,19 @@ public interface AddressSetView extends Iterable<AddressRange> {
public boolean isEmpty();
/**
* Get the minimum address for this address set.
* NOTE: An {@link AddressRange} should generally not be formed using this address
* and {@link #getMaxAddress()} since it may span multiple {@link AddressSpace}s.
*
* @return the minimum address for this set. Returns null if the set is empty.
*/
public Address getMinAddress();
/**
* Get the maximum address for this address set.
* NOTE: An {@link AddressRange} should generally not be formed using this address
* and {@link #getMaxAddress()} since it may span multiple {@link AddressSpace}s.
*
* @return the maximum address for this set. Returns null if the set is empty.
*/
public Address getMaxAddress();
@ -151,8 +161,9 @@ public interface AddressSetView extends Iterable<AddressRange> {
public boolean intersects(AddressSetView addrSet);
/**
* Determine if the start and end range
* intersects with the specified address set.
* Determine if the start and end range intersects with the specified address set.
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
* @param start start of range
* @param end end of range
* @return true if the given range intersects this address set.
@ -171,6 +182,8 @@ public interface AddressSetView extends Iterable<AddressRange> {
/**
* Computes the intersection of this address set with the given address range.
* This method does not modify this address set.
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
* @param start start of range
* @param end end of range
* @return AddressSet a new address set that contains all addresses that are

View file

@ -305,7 +305,10 @@ public interface Program extends DataTypeManagerDomainObject, ProgramArchitectur
public ProgramContext getProgramContext();
/**
* get the program's minimum address.
* Get the program's minimum address.
* NOTE: An {@link AddressRange} should generally not be formed using this address
* and {@link #getMaxAddress()} since it may span multiple {@link AddressSpace}s.
*
* @return the program's minimum address or null if no memory blocks
* have been defined in the program.
*/
@ -313,6 +316,9 @@ public interface Program extends DataTypeManagerDomainObject, ProgramArchitectur
/**
* Get the programs maximum address.
* NOTE: An {@link AddressRange} should generally not be formed using this address
* and {@link #getMinAddress()} since it may span multiple {@link AddressSpace}s.
*
* @return the program's maximum address or null if no memory blocks
* have been defined in the program.
*/

View file

@ -18,6 +18,7 @@ package ghidra.program.model.util;
import java.util.Iterator;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.util.Saveable;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.DuplicateNameException;
@ -154,6 +155,9 @@ public interface PropertyMapManager {
/**
* Removes all properties in the given range from all user
* defined PropertyMaps.
* The specified start and end addresses must form a valid range within
* a single {@link AddressSpace}.
*
* @param startAddr the first address in the range of addresses where
* propertie values are to be removed.
* @param endAddr the last address in the range of addresses where

View file

@ -152,9 +152,7 @@ public class RegisterValueStore {
while (rangeIt.hasNext()) {
list.add(rangeIt.next());
}
Iterator<AddressRange> it = list.iterator();
while (it.hasNext()) {
AddressRange indexRange = it.next();
for (AddressRange indexRange : list) {
Address rangeStart = indexRange.getMinAddress();
Address rangeEnd = indexRange.getMaxAddress();
if (rangeStart.compareTo(start) > 0) {
@ -194,6 +192,8 @@ public class RegisterValueStore {
*/
public void clearValue(Address start, Address end, Register register) {
AddressRange.checkValidRange(start, end);
flushWriteCache();
// if the mask is all on, then just clear any values that are stored in this range
@ -208,9 +208,7 @@ public class RegisterValueStore {
while (rangeIt.hasNext()) {
list.add(rangeIt.next());
}
Iterator<AddressRange> it = list.iterator();
while (it.hasNext()) {
AddressRange indexRange = it.next();
for (AddressRange indexRange : list) {
Address rangeStart = indexRange.getMinAddress();
Address rangeEnd = indexRange.getMaxAddress();