mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GT-3148: Corrected conversion of BigInteger to byte array to remove
array out of bounds exception in PowerPC vectorPermute pcodeop
This commit is contained in:
parent
d9da0f0b66
commit
fccabd9950
2 changed files with 43 additions and 42 deletions
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package ghidra.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -284,7 +283,7 @@ public class NumericUtilitiesTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetUnsigndeAlignedValue() {
|
||||
public void testGetUnsignedAlignedValue() {
|
||||
|
||||
assertEquals(0, NumericUtilities.getUnsignedAlignedValue(0xffffffffffffffffL, 8));
|
||||
assertEquals(0xfffffffffffffff8L,
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.program.emulation;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.pcode.emulate.Emulate;
|
||||
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
||||
import ghidra.pcode.emulate.callother.CountLeadingZerosOpBehavior;
|
||||
|
@ -22,25 +24,21 @@ import ghidra.pcode.emulate.callother.OpBehaviorOther;
|
|||
import ghidra.pcode.memstate.MemoryState;
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||
|
||||
|
||||
public PPCEmulateInstructionStateModifier(Emulate emu) {
|
||||
super(emu);
|
||||
|
||||
registerPcodeOpBehavior("countLeadingZeros", new CountLeadingZerosOpBehavior());
|
||||
registerPcodeOpBehavior("vectorPermute", new vectorPermuteOpBehavior());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private class vectorPermuteOpBehavior implements OpBehaviorOther {
|
||||
|
||||
@Override
|
||||
public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) {
|
||||
int i;
|
||||
|
||||
if (out == null) {
|
||||
throw new LowlevelError("CALLOTHER: Vector permute op missing required output");
|
||||
|
@ -50,7 +48,7 @@ public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateM
|
|||
throw new LowlevelError(
|
||||
"CALLOTHER: Vector permute op requires three non-constant varnode input");
|
||||
}
|
||||
for (i = 1; i < 4; i++) {
|
||||
for (int i = 1; i < 4; i++) {
|
||||
if (inputs[i].getSize() == 0 || inputs[i].isConstant()) {
|
||||
throw new LowlevelError(
|
||||
"CALLOTHER: Vector permute op requires three non-constant varnode input");
|
||||
|
@ -61,49 +59,53 @@ public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateM
|
|||
Varnode in1 = inputs[1];
|
||||
Varnode in2 = inputs[2];
|
||||
Varnode in3 = inputs[3];
|
||||
if ((in1.getSize() != 16) || (in2.getSize() != 16) || (in3.getSize() != 16) || (out.getSize() != 16)) {
|
||||
if ((in1.getSize() != 16) || (in2.getSize() != 16) || (in3.getSize() != 16) ||
|
||||
(out.getSize() != 16)) {
|
||||
throw new LowlevelError(
|
||||
"CALLOTHER: Vector permute op inputs/output must be 16bytes long");
|
||||
}
|
||||
|
||||
MemoryState memoryState = emu.getMemoryState();
|
||||
|
||||
// Combine two 16-byte inputs to form single 32-byte input
|
||||
BigInteger src = memoryState.getBigInteger(in1, false);
|
||||
src = src.shiftLeft(128);
|
||||
src = src.or(memoryState.getBigInteger(in2, false));
|
||||
byte[] srcin = getUnsignedValueArray(src.toByteArray(), 32);
|
||||
|
||||
// I need to force the srcarray and permute arrays to be a specific length
|
||||
// I can find no direct way to do this which stinks. The ensureCapacity
|
||||
// would work, but I need the padding at the beginning.
|
||||
byte[] srcin = src.toByteArray();
|
||||
byte[] srcarray;
|
||||
if (srcin.length != 32) {
|
||||
i = 32-srcin.length;
|
||||
srcarray = new byte[32];
|
||||
System.arraycopy(srcin, 0, srcarray, i, srcin.length);
|
||||
}
|
||||
else {
|
||||
srcarray = srcin;
|
||||
}
|
||||
|
||||
// Get 16-byte permute input
|
||||
byte[] pin = memoryState.getBigInteger(in3, false).toByteArray();
|
||||
byte[] permute;
|
||||
if (pin.length != 16) {
|
||||
i = 16 - pin.length;
|
||||
permute = new byte[16];
|
||||
System.arraycopy(pin, 0, permute, i, pin.length);
|
||||
}
|
||||
else {
|
||||
permute = pin;
|
||||
}
|
||||
byte[] outarray = new byte[16];
|
||||
byte[] permute = getUnsignedValueArray(pin, 16);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
outarray[i] = srcarray[(permute[i] & 0x1f)];
|
||||
// Generate 16-byte output
|
||||
byte[] outarray = new byte[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
outarray[i] = srcin[(permute[i] & 0x1f)];
|
||||
}
|
||||
|
||||
memoryState.setValue(out, new BigInteger(outarray));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an unsigned value array from variable length srcBytes extending or truncating
|
||||
* bytes as needed to ensure a returned length of byteLength. The MSB is located
|
||||
* at byte index 0, therefore adjustments may be needed to ensure that the LSB retains
|
||||
* its position in the least-significant byte. A short srcBytes array will result in
|
||||
* zero-filled most-significant bytes within the result.
|
||||
* @param srcBytes unsigned source value array
|
||||
* @param byteLength desired result value length in bytes
|
||||
* @return a value byte array of the specified byteLength
|
||||
*/
|
||||
private static byte[] getUnsignedValueArray(byte[] srcBytes, int byteLength) {
|
||||
if (srcBytes.length == byteLength) {
|
||||
return srcBytes;
|
||||
}
|
||||
byte[] result = new byte[byteLength];
|
||||
int srcStartIndex = Math.max(0, srcBytes.length - byteLength); // discard excessive most-significant bytes
|
||||
int copyCount = Math.min(byteLength, srcBytes.length); // limit copy to requested number of bytes
|
||||
int destStartIndex = byteLength - copyCount; // adjust if too few bytes provided
|
||||
System.arraycopy(srcBytes, srcStartIndex, result, destStartIndex, copyCount);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue