Fix Preconditions.checkArrayPayloadElements

The previous implementation did not correctly handle negative numbers.
This commit is contained in:
Ben Gruver 2019-09-12 11:30:27 -07:00
parent f8d6f15768
commit 751fe1ce61
2 changed files with 33 additions and 14 deletions

View File

@ -220,13 +220,14 @@ public class Preconditions {
} }
public static <L extends List<? extends Number>> L checkArrayPayloadElements(int elementWidth, L elements) { public static <L extends List<? extends Number>> L checkArrayPayloadElements(int elementWidth, L elements) {
// mask of all bits that do not fit into an 'elementWidth'-byte number long maxValue = (1L << ((8 * elementWidth) - 1)) - 1;
long bitmask = -1L << (elementWidth * 8); long minValue = -maxValue - 1;
for (Number element : elements) { for (Number element : elements) {
if ((element.longValue() & bitmask) != 0) { if (element.longValue() < minValue || element.longValue() > maxValue) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format("Number %d must fit into a %d-byte number", element.longValue(), elementWidth)); String.format("%d does not fit into a %d-byte signed integer",
element.longValue(), elementWidth));
} }
} }

View File

@ -1,23 +1,41 @@
package org.jf.util; package org.jf.util;
import java.util.ArrayList; import com.google.common.collect.ImmutableList;
import java.util.List;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.formats.ArrayPayload;
import org.jf.dexlib2.util.Preconditions; import org.jf.dexlib2.util.Preconditions;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
public class PreconditionsTest { public class PreconditionsTest {
private void verifyArrayPayloadElementIsValid(int elementWidth, long value) {
Preconditions.checkArrayPayloadElements(elementWidth, ImmutableList.of(value));
}
private void verifyArrayPayloadElementIsInvalid(int elementWidth, long value) {
try {
Preconditions.checkArrayPayloadElements(elementWidth, ImmutableList.of(value));
Assert.fail();
} catch (IllegalArgumentException ex) {
// expected exception
}
}
@Test @Test
public void checkArrayPayloadElements() { public void checkArrayPayloadElements() {
int intSize = 4; verifyArrayPayloadElementIsValid(8, Long.MAX_VALUE);
int bigNumber = 16843071; verifyArrayPayloadElementIsValid(8, Long.MIN_VALUE);
List<Number> numbers = new ArrayList<>(); verifyArrayPayloadElementIsValid(4, Integer.MAX_VALUE);
numbers.add(bigNumber); verifyArrayPayloadElementIsValid(4, Integer.MIN_VALUE);
verifyArrayPayloadElementIsValid(2, Short.MAX_VALUE);
verifyArrayPayloadElementIsValid(2, Short.MIN_VALUE);
verifyArrayPayloadElementIsValid(1, Byte.MAX_VALUE);
verifyArrayPayloadElementIsValid(1, Byte.MIN_VALUE);
// Shouldn't throw any exceptions, payload is correct. verifyArrayPayloadElementIsInvalid(4, ((long) Integer.MAX_VALUE) + 1);
Preconditions.checkArrayPayloadElements(intSize, numbers); verifyArrayPayloadElementIsInvalid(4, ((long) Integer.MIN_VALUE) - 1);
verifyArrayPayloadElementIsInvalid(2, ((long) Short.MAX_VALUE) + 1);
verifyArrayPayloadElementIsInvalid(2, ((long) Short.MIN_VALUE) - 1);
verifyArrayPayloadElementIsInvalid(1, ((long) Byte.MAX_VALUE) + 1);
verifyArrayPayloadElementIsInvalid(1, ((long) Byte.MIN_VALUE) - 1);
} }
} }