mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-1903 refactor out ArrayUtilities, fix BitFieldDataType ENDIANness
Nuke ArrayUtilties and replace it with built-in methods available in jdk Arrays class or use DataConverter for endianness conversion. Exclude ENDIAN setting for BitFieldDataType.
This commit is contained in:
parent
a94082bb67
commit
2a4a7747e6
10 changed files with 44 additions and 204 deletions
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.file.formats.coff;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
|
@ -24,7 +26,6 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
|||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
public class CoffArchiveFileSystemFactory implements
|
||||
GFileSystemFactoryByteProvider<CoffArchiveFileSystem>, GFileSystemProbeBytesOnly {
|
||||
|
@ -48,7 +49,8 @@ public class CoffArchiveFileSystemFactory implements
|
|||
|
||||
@Override
|
||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||
return ArrayUtilities.arrayRangesEquals(CoffArchiveConstants.MAGIC_BYTES, 0, startBytes, 0,
|
||||
CoffArchiveConstants.MAGIC_BYTES.length);
|
||||
return Arrays.equals(
|
||||
CoffArchiveConstants.MAGIC_BYTES, 0, CoffArchiveConstants.MAGIC_BYTES.length,
|
||||
startBytes, 0, CoffArchiveConstants.MAGIC_BYTES.length);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,13 +20,12 @@ import java.io.IOException;
|
|||
import ghidra.app.util.bin.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
public class Apple8900Header implements StructConverter {
|
||||
|
||||
private byte[] magic;
|
||||
private byte[] version;
|
||||
private byte encrypted;
|
||||
private byte[] magic; // "8900"
|
||||
private byte[] version; // "1.0"
|
||||
private byte encrypted; // format, plaintext=0x4, encrypted=0x3
|
||||
private byte[] unknown0;
|
||||
private int sizeOfData;
|
||||
private int footerSignatureOffset;
|
||||
|
@ -61,7 +60,7 @@ public class Apple8900Header implements StructConverter {
|
|||
}
|
||||
|
||||
public String getVersion() {
|
||||
return new String(ArrayUtilities.reverse(version));
|
||||
return new String(version);
|
||||
}
|
||||
|
||||
public boolean isEncrypted() {
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.file.formats.ios.dmg;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -29,7 +31,6 @@ import ghidra.util.Msg;
|
|||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.CryptoException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
/**
|
||||
* Handles probing for and creating {@link DmgClientFileSystem} instances.
|
||||
|
@ -58,10 +59,10 @@ public class DmgClientFileSystemFactory implements
|
|||
}
|
||||
|
||||
private static boolean isEncrypted(byte[] startBytes) {
|
||||
return ArrayUtilities.arrayRangesEquals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v1, 0,
|
||||
DmgConstants.DMG_MAGIC_BYTES_v1.length) ||
|
||||
ArrayUtilities.arrayRangesEquals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v2, 0,
|
||||
DmgConstants.DMG_MAGIC_BYTES_v2.length);
|
||||
return Arrays.equals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v1.length,
|
||||
DmgConstants.DMG_MAGIC_BYTES_v1, 0, DmgConstants.DMG_MAGIC_BYTES_v1.length) ||
|
||||
Arrays.equals(startBytes, 0, DmgConstants.DMG_MAGIC_BYTES_v2.length,
|
||||
DmgConstants.DMG_MAGIC_BYTES_v2, 0, DmgConstants.DMG_MAGIC_BYTES_v2.length);
|
||||
}
|
||||
|
||||
private static boolean isEncrypted(ByteProvider bp) {
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.file.formats.ios.img2;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
|
@ -23,7 +25,6 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
|||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
public class Img2FileSystemFactory implements GFileSystemFactoryByteProvider<Img2FileSystem>, GFileSystemProbeBytesOnly {
|
||||
|
||||
|
@ -34,8 +35,8 @@ public class Img2FileSystemFactory implements GFileSystemFactoryByteProvider<Img
|
|||
|
||||
@Override
|
||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||
return ArrayUtilities.arrayRangesEquals(startBytes, 0, Img2Constants.IMG2_SIGNATURE_BYTES,
|
||||
0, Img2Constants.IMG2_SIGNATURE_BYTES.length);
|
||||
return Arrays.equals(startBytes, 0, Img2Constants.IMG2_SIGNATURE_BYTES.length,
|
||||
Img2Constants.IMG2_SIGNATURE_BYTES, 0, Img2Constants.IMG2_SIGNATURE_BYTES.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.file.formats.ios.img3;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
|
@ -23,19 +25,18 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
|||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
public class Img3FileSystemFactory
|
||||
implements GFileSystemFactoryByteProvider<Img3FileSystem>, GFileSystemProbeBytesOnly {
|
||||
@Override
|
||||
public int getBytesRequired() {
|
||||
return Img3Constants.IMG3_SIGNATURE_LENGTH;
|
||||
return Img3Constants.IMG3_SIGNATURE_BYTES.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||
return ArrayUtilities.arrayRangesEquals(startBytes, 0, Img3Constants.IMG3_SIGNATURE_BYTES,
|
||||
0, Img3Constants.IMG3_SIGNATURE_LENGTH);
|
||||
return Arrays.equals(startBytes, 0, Img3Constants.IMG3_SIGNATURE_BYTES.length,
|
||||
Img3Constants.IMG3_SIGNATURE_BYTES, 0, Img3Constants.IMG3_SIGNATURE_BYTES.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.file.formats.java;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
@ -26,7 +28,6 @@ import ghidra.formats.gfilesystem.factory.GFileSystemFactoryByteProvider;
|
|||
import ghidra.formats.gfilesystem.factory.GFileSystemProbeBytesOnly;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
/**
|
||||
* Creates instances of {@link JavaClassDecompilerFileSystem}.
|
||||
|
@ -42,8 +43,8 @@ public class JavaClassDecompilerFileSystemFactory implements
|
|||
@Override
|
||||
public boolean probeStartBytes(FSRL containerFSRL, byte[] startBytes) {
|
||||
return JadProcessWrapper.isJadPresent() &&
|
||||
ArrayUtilities.arrayRangesEquals(startBytes, 0, JavaClassConstants.MAGIC_BYTES, 0,
|
||||
JavaClassConstants.MAGIC_BYTES.length) &&
|
||||
Arrays.equals(startBytes, 0, JavaClassConstants.MAGIC_BYTES.length,
|
||||
JavaClassConstants.MAGIC_BYTES, 0, JavaClassConstants.MAGIC_BYTES.length) &&
|
||||
"class".equalsIgnoreCase(FilenameUtils.getExtension(containerFSRL.getName()));
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
*/
|
||||
package docking.widgets.table;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.*;
|
||||
|
@ -30,7 +31,6 @@ import org.apache.logging.log4j.Logger;
|
|||
import ghidra.util.Msg;
|
||||
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||
import ghidra.util.datastruct.WeakSet;
|
||||
import utilities.util.ArrayUtilities;
|
||||
import utilities.util.reflection.ReflectionUtilities;
|
||||
|
||||
/**
|
||||
|
@ -405,7 +405,7 @@ public class RowObjectSelectionManager<T> extends DefaultListSelectionModel
|
|||
|
||||
private boolean restoreSelectedRows(int[] rows) {
|
||||
traceRows("restoreSelectedRows(): ", rows);
|
||||
if (ArrayUtilities.isArrayPrimativeEqual(rows, table.getSelectedRows())) {
|
||||
if (Arrays.equals(rows, table.getSelectedRows())) {
|
||||
trace("\tselection hasn't changed--nothing to do");
|
||||
// the selection is the same, nothing to change; don't send out excess events
|
||||
return false;
|
||||
|
|
|
@ -24,8 +24,8 @@ import ghidra.pcode.utils.Utils;
|
|||
import ghidra.program.model.data.StringRenderParser.StringParseException;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.util.DataConverter;
|
||||
import ghidra.util.StringFormat;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
/**
|
||||
* Base type for integer data types such as {@link CharDataType chars}, {@link IntegerDataType
|
||||
|
@ -166,25 +166,14 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!ENDIAN.isBigEndian(settings, buf)) {
|
||||
bytes = ArrayUtilities.reverse(bytes);
|
||||
}
|
||||
DataConverter dc = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf));
|
||||
|
||||
if (size > 8) {
|
||||
if (!isSigned()) {
|
||||
// ensure that bytes are treated as unsigned
|
||||
byte[] unsignedBytes = new byte[bytes.length + 1];
|
||||
System.arraycopy(bytes, 0, unsignedBytes, 1, bytes.length);
|
||||
bytes = unsignedBytes;
|
||||
}
|
||||
return new BigInteger(bytes);
|
||||
return dc.getBigInteger(bytes, size, isSigned());
|
||||
}
|
||||
|
||||
// Use long when possible
|
||||
long val = 0;
|
||||
for (byte b : bytes) {
|
||||
val = (val << 8) + (b & 0x0ffL);
|
||||
}
|
||||
long val = dc.getValue(bytes, size);
|
||||
return new Scalar(size * 8, val, isSigned());
|
||||
}
|
||||
|
||||
|
@ -294,11 +283,8 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
|||
return "??";
|
||||
}
|
||||
|
||||
if (!ENDIAN.isBigEndian(settings, buf)) {
|
||||
bytes = ArrayUtilities.reverse(bytes);
|
||||
}
|
||||
|
||||
BigInteger value = new BigInteger(bytes);
|
||||
BigInteger value = DataConverter.getInstance(ENDIAN.isBigEndian(settings, buf))
|
||||
.getBigInteger(bytes, size, true);
|
||||
|
||||
if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) {
|
||||
return StringDataInstance.getCharRepresentation(this, bytes, settings);
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.docking.settings.*;
|
||||
|
@ -22,7 +24,6 @@ import ghidra.program.model.mem.MemBuffer;
|
|||
import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.util.DataConverter;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
/**
|
||||
* <code>BitFieldDataType</code> provides a means of defining a minimally sized bit-field
|
||||
|
@ -251,7 +252,11 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
*/
|
||||
@Override
|
||||
public final SettingsDefinition[] getSettingsDefinitions() {
|
||||
return baseDataType.getSettingsDefinitions();
|
||||
// exclude any ENDIAN setting that the base data type might support
|
||||
List<SettingsDefinition> baseDTSettings =
|
||||
new ArrayList<>(Arrays.asList(baseDataType.getSettingsDefinitions()));
|
||||
baseDTSettings.remove(EndianSettingsDefinition.DEF);
|
||||
return baseDTSettings.toArray(SettingsDefinition[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -369,16 +374,6 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
return BigInteger.ZERO;
|
||||
}
|
||||
try {
|
||||
|
||||
byte[] bytes = new byte[storageSize];
|
||||
if (buf.getBytes(bytes, 0) != storageSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!EndianSettingsDefinition.ENDIAN.isBigEndian(settings, buf)) {
|
||||
bytes = ArrayUtilities.reverse(bytes);
|
||||
}
|
||||
|
||||
BigInteger big = buf.getBigInteger(0, storageSize, false);
|
||||
BigInteger pow = BigInteger.valueOf(2).pow(effectiveBitSize);
|
||||
BigInteger mask = pow.subtract(BigInteger.ONE);
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package utilities.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
|
||||
import ghidra.util.SystemUtilities;
|
||||
|
||||
public final class ArrayUtilities {
|
||||
|
||||
/**
|
||||
* Returns a new copy of the specified byte {@code array} with the elements in reversed order.
|
||||
*
|
||||
* @param array byte array to reverse
|
||||
* @return new array instance with elements in reverse order
|
||||
*/
|
||||
public static byte[] reverse(byte[] array) {
|
||||
|
||||
byte[] reversed = new byte[array.length];
|
||||
|
||||
for (int i = 0; i < reversed.length; i++) {
|
||||
reversed[i] = array[array.length - 1 - i];
|
||||
}
|
||||
return reversed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two primitive arrays for equality
|
||||
*
|
||||
* @param o1 the first array
|
||||
* @param o2 the second array
|
||||
* @return true if each element of the array is equal
|
||||
* @throws IllegalArgumentException if either argument is not an array
|
||||
*/
|
||||
public static boolean isArrayPrimativeEqual(Object o1, Object o2) {
|
||||
if (o1 == null) {
|
||||
return (o2 == null);
|
||||
}
|
||||
|
||||
if (o2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Class<? extends Object> class1 = o1.getClass();
|
||||
if (!class1.isArray()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Object parameters must be an array! Instead found class: " + class1);
|
||||
}
|
||||
|
||||
Class<? extends Object> class2 = o2.getClass();
|
||||
if (!class2.isArray()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Object parameters must be an array! Instead found class: " + class2);
|
||||
}
|
||||
|
||||
if (Array.getLength(o1) != Array.getLength(o2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Array.getLength(o1); i++) {
|
||||
if (!SystemUtilities.isEqual(Array.get(o1, i), Array.get(o2, i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a portion of byte array b1 equals an equally sized portion of byte array
|
||||
* b2.
|
||||
* <p>
|
||||
* If the sizes of b1 or b2 do not allow for a full comparison of {@code len} bytes, this
|
||||
* function will return false.
|
||||
* <p>
|
||||
* @param b1 first byte array
|
||||
* @param start_b1 offset to start comparison in b1
|
||||
* @param b2 second byte array
|
||||
* @param start_b2 offset to start comparison in b2
|
||||
* @param len number of bytes to compare
|
||||
* @return true or false if the portion is equal
|
||||
*/
|
||||
public static boolean arrayRangesEquals(byte[] b1, int start_b1, byte[] b2, int start_b2,
|
||||
int len) {
|
||||
if (start_b1 + len > b1.length || start_b2 + len > b2.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (b1[start_b1 + i] != b2[start_b2 + i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the given array with the provided element appended. The length of
|
||||
* the returned array will be one element greater than the given array.
|
||||
*
|
||||
* @param array The array to copy.
|
||||
* @param element The element to append to the copy.
|
||||
* @return A copy of the given array with the provided element appended.
|
||||
*/
|
||||
public static <T> T[] copyAndAppend(T[] array, T element) {
|
||||
T[] newArray = Arrays.copyOf(array, array.length + 1);
|
||||
newArray[array.length] = element;
|
||||
return newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two byte arrays by their corresponding entries
|
||||
*
|
||||
* If the two arrays have differing lengths, the shorter precedes the longer. Otherwise, they
|
||||
* are compared as in C's {@code memcmp}, except that Java {@code byte}s are signed.
|
||||
* @param a the first array
|
||||
* @param b the second array
|
||||
* @return a comparison result as in {@link Comparable#compareTo(Object)}
|
||||
*/
|
||||
public static int compare(byte[] a, byte[] b) {
|
||||
int result;
|
||||
result = a.length - b.length;
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
result = a[i] - b[i];
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue