mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-28 21:10:05 +08:00
GP-6654: Fix state.get/setVar(size=0)
This commit is contained in:
+3
@@ -761,6 +761,9 @@ public enum TraceEmulationIntegration {
|
|||||||
value)) {
|
value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Address end = address.addWrap(length - 1);
|
Address end = address.addWrap(length - 1);
|
||||||
if (address.compareTo(end) <= 0) {
|
if (address.compareTo(end) <= 0) {
|
||||||
written.add(address, end);
|
written.add(address, end);
|
||||||
|
|||||||
+69
@@ -32,6 +32,7 @@ import ghidra.pcode.emu.PcodeEmulator;
|
|||||||
import ghidra.pcode.emu.PcodeThread;
|
import ghidra.pcode.emu.PcodeThread;
|
||||||
import ghidra.pcode.exec.*;
|
import ghidra.pcode.exec.*;
|
||||||
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
|
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
|
||||||
|
import ghidra.pcode.exec.trace.TraceEmulationIntegration.TraceWriter;
|
||||||
import ghidra.pcode.exec.trace.TraceEmulationIntegration.Writer;
|
import ghidra.pcode.exec.trace.TraceEmulationIntegration.Writer;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressRangeImpl;
|
import ghidra.program.model.address.AddressRangeImpl;
|
||||||
@@ -55,6 +56,74 @@ public class BytesTracePcodeEmulatorTest extends AbstractTracePcodeEmulatorTest
|
|||||||
return new PcodeEmulator(platform.getLanguage(), writer.callbacks());
|
return new PcodeEmulator(platform.getLanguage(), writer.callbacks());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetVarSize0() throws Throwable {
|
||||||
|
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
|
||||||
|
initTrace(tb, """
|
||||||
|
RIP = 0x00400000;
|
||||||
|
""",
|
||||||
|
List.of());
|
||||||
|
|
||||||
|
Writer writer = createWriter(tb.host, 0);
|
||||||
|
PcodeEmulator emu = createEmulator(tb.host, writer);
|
||||||
|
|
||||||
|
emu.getSharedState().setVar(tb.addr(0x00400000), 0, false, tb.arr());
|
||||||
|
TraceWriter tw = (TraceWriter) writer;
|
||||||
|
assertEquals(tb.set(), tw.memWritten);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetVarSize0Uninit() throws Throwable {
|
||||||
|
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
|
||||||
|
initTrace(tb, """
|
||||||
|
RIP = 0x00400000;
|
||||||
|
""",
|
||||||
|
List.of());
|
||||||
|
|
||||||
|
Writer writer = createWriter(tb.host, 0);
|
||||||
|
PcodeEmulator emu = createEmulator(tb.host, writer);
|
||||||
|
PcodeExecutorState<byte[]> state = emu.getSharedState();
|
||||||
|
Address addr = tb.addr(0x00400000);
|
||||||
|
|
||||||
|
byte[] result = state.getVar(addr, 0, false, Reason.EXECUTE_READ);
|
||||||
|
assertArrayEquals(new byte[0], result);
|
||||||
|
|
||||||
|
assertNull(state.getNextEntryInternal(addr.getAddressSpace(), 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetVarSize0Init() throws Throwable {
|
||||||
|
try (ToyDBTraceBuilder tb = new ToyDBTraceBuilder("Test", "x86:LE:64:default")) {
|
||||||
|
// Put some known data in a place likely to show in erroneous "uninitialized" set
|
||||||
|
initTrace(tb, """
|
||||||
|
RIP = 0x00400000;
|
||||||
|
*:8 RIP = 0xdeadbeefcafeface;
|
||||||
|
""",
|
||||||
|
List.of());
|
||||||
|
|
||||||
|
Writer writer = createWriter(tb.host, 0);
|
||||||
|
PcodeEmulator emu = createEmulator(tb.host, writer);
|
||||||
|
PcodeExecutorState<byte[]> state = emu.getSharedState();
|
||||||
|
Address addr = tb.addr(0x00400000);
|
||||||
|
state.setVar(addr, 4, false, tb.arr(1, 2, 3, 4));
|
||||||
|
|
||||||
|
var entry = state.getNextEntryInternal(addr.getAddressSpace(), 0);
|
||||||
|
assertEquals(0x00400000L, entry.getKey().longValue());
|
||||||
|
assertArrayEquals(tb.arr(1, 2, 3, 4), entry.getValue());
|
||||||
|
assertNull(state.getNextEntryInternal(addr.getAddressSpace(), 0x00400004));
|
||||||
|
|
||||||
|
byte[] result = state.getVar(addr, 0, false, Reason.EXECUTE_READ);
|
||||||
|
assertArrayEquals(tb.arr(), result);
|
||||||
|
|
||||||
|
entry = state.getNextEntryInternal(addr.getAddressSpace(), 0);
|
||||||
|
assertEquals(0x00400000L, entry.getKey().longValue());
|
||||||
|
assertArrayEquals(tb.arr(1, 2, 3, 4), entry.getValue());
|
||||||
|
assertNull(state.getNextEntryInternal(addr.getAddressSpace(), 0x00400004));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test a single instruction
|
* Test a single instruction
|
||||||
*
|
*
|
||||||
|
|||||||
+6
@@ -16,6 +16,7 @@
|
|||||||
package ghidra.pcode.exec;
|
package ghidra.pcode.exec;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
|
||||||
@@ -103,4 +104,9 @@ public abstract class AbstractPcodeExecutorState<A, T> implements PcodeExecutorS
|
|||||||
public void clear() {
|
public void clear() {
|
||||||
piece.clear();
|
piece.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entry<Long, T> getNextEntryInternal(AddressSpace space, long offset) {
|
||||||
|
return piece.getNextEntryInternal(space, offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
@@ -15,6 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.pcode.exec;
|
package ghidra.pcode.exec;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import generic.ULongSpan;
|
||||||
|
import generic.ULongSpan.ULongSpanSet;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.lang.Language;
|
import ghidra.program.model.lang.Language;
|
||||||
|
|
||||||
@@ -45,4 +51,24 @@ public class BytesPcodeExecutorStatePiece
|
|||||||
protected BytesPcodeExecutorStateSpace newSpace(AddressSpace space) {
|
protected BytesPcodeExecutorStateSpace newSpace(AddressSpace space) {
|
||||||
return new BytesPcodeExecutorStateSpace(language, space, this);
|
return new BytesPcodeExecutorStateSpace(language, space, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Entry<Long, byte[]> getNextEntryInternal(AddressSpace space, long offset) {
|
||||||
|
BytesPcodeExecutorStateSpace s = getForSpace(space, false);
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ULongSpanSet initialized = s.bytes.getInitialized(0, -1);
|
||||||
|
ULongSpan span = initialized.spanContaining(offset);
|
||||||
|
if (span == null) {
|
||||||
|
var it = initialized.intersecting(ULongSpan.span(offset, -1)).iterator();
|
||||||
|
if (!it.hasNext()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
span = it.next();
|
||||||
|
}
|
||||||
|
byte[] data = new byte[(int) span.length()];
|
||||||
|
s.bytes.getData(span.min(), data);
|
||||||
|
return Map.entry(span.min(), data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -180,6 +180,9 @@ public class BytesPcodeExecutorStateSpace {
|
|||||||
* @return the uninitialized offset ranges
|
* @return the uninitialized offset ranges
|
||||||
*/
|
*/
|
||||||
protected AddressSetView computeUninitialized(long offset, int size) {
|
protected AddressSetView computeUninitialized(long offset, int size) {
|
||||||
|
if (size == 0) {
|
||||||
|
return new AddressSet();
|
||||||
|
}
|
||||||
long max = offset + size - 1;
|
long max = offset + size - 1;
|
||||||
if (Long.compareUnsigned(max, space.getMaxAddress().getOffset()) <= 0 &&
|
if (Long.compareUnsigned(max, space.getMaxAddress().getOffset()) <= 0 &&
|
||||||
Long.compareUnsigned(offset, max) <= 0) {
|
Long.compareUnsigned(offset, max) <= 0) {
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ public interface PcodeStateCallbacks {
|
|||||||
* @return the address set
|
* @return the address set
|
||||||
*/
|
*/
|
||||||
static AddressSet rngSet(AddressSpace space, long offset, int length) {
|
static AddressSet rngSet(AddressSpace space, long offset, int length) {
|
||||||
|
if (length == 0) {
|
||||||
|
return new AddressSet();
|
||||||
|
}
|
||||||
Address min = space.getAddress(offset);
|
Address min = space.getAddress(offset);
|
||||||
return new AddressSet(min, min.add(length - 1));
|
return new AddressSet(min, min.add(length - 1));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user