GP-3687 fixed potential replacement of goto reference with data

reference in x86 PIC CALL to fallthru address
This commit is contained in:
emteere 2023-08-16 14:14:30 +00:00
parent c32b6d6bdb
commit c0c04ff789
2 changed files with 61 additions and 4 deletions

View File

@ -15,13 +15,11 @@
*/
package ghidra.program.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.math.BigInteger;
import org.junit.*;
import org.junit.Test;
import generic.test.AbstractGenericTest;
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
@ -34,6 +32,7 @@ import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.listing.*;
import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.Reference;
import ghidra.program.model.symbol.ReferenceIterator;
import ghidra.program.util.SymbolicPropogator.Value;
import ghidra.util.exception.NotFoundException;
import ghidra.util.task.TaskMonitor;
@ -307,6 +306,53 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
assertNoOperandReference(0, instr);
assertOperandReferenceTo(1, instr, addr("0x00040100"));
}
@Test
public void testPIC_Call_X86_64() throws Exception {
builder = new ProgramBuilder("PICCode", ProgramBuilder._X64, "gcc", this);
// entry
// 48 83 ec 28 SUB RSP,0x28
// e8 00 00 00 00 CALL LAB_140020119
// LAB_140020119
// 8f c3 POP RBX
// 48 8d 43 e0 LEA RAX,[RBX + -0x20]
// ff d0 CALL RAX
// 48 83 c4 28 ADD RSP,0x28
// c3 RET
builder.setBytes("0x140020110",
"48 83 ec 28 e8 00 00 00 00 8f c3 48 8d 43 e0 ff d0 48 83 c4 28 c3");
builder.setBytes("0x1400200f9",
"15 02 2f 00 00 89 05 e8 b9 00 00 48 83 c4 38");
builder.disassemble("0x140020110", 21);
analyzer = new ConstantPropagationAnalyzer();
program = builder.getProgram();
program.startTransaction("Test");
Address codeStart = addr("140020110");
Listing listing = program.getListing();
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(21));
analyze(addressSet);
Instruction instr = listing.getInstructionAt(addr("0x140020114"));
assertOperandReferenceTo(0, instr, addr("0x140020119"));
instr = listing.getInstructionAt(addr("0x140020119"));
ReferenceIterator referenceIteratorTo = instr.getReferenceIteratorTo();
Reference ref = referenceIteratorTo.next();
assertTrue(ref.getReferenceType().isJump());
instr = listing.getInstructionAt(addr("0x14002011f"));
Reference[] referencesFrom = instr.getReferencesFrom();
assertTrue(referencesFrom[0].getReferenceType().isFlow());
assertEquals("1400200f9", referencesFrom[0].getToAddress().toString());
}
private void assertNoOperandReference(int opIndex, Instruction instr) {
Reference[] refs = instr.getOperandReferences(opIndex);

View File

@ -303,6 +303,17 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan
* @return combined reference type, or the newType if unable to combine
*/
private RefType combineReferenceType(RefType newType, RefType oldType) {
// check if types are the same, if same no use doing work replacing reference
if (newType == oldType) {
return oldType;
}
// any flow reference should be used over the existing ref to the same location
if (newType.isFlow()) {
return newType; // allow any new flow ref to replace old type
}
if (oldType.isFlow()) {
return oldType; // always keep flow over new data ref
}
if (newType == RefType.DATA) {
if (oldType.isData()) {
return oldType;