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:
dev747368 2022-04-06 20:43:31 +00:00
parent a94082bb67
commit 2a4a7747e6
10 changed files with 44 additions and 204 deletions

View file

@ -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);
}
}

View file

@ -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() {

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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()));
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;
}
}