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) {
// mask of all bits that do not fit into an 'elementWidth'-byte number
long bitmask = -1L << (elementWidth * 8);
long maxValue = (1L << ((8 * elementWidth) - 1)) - 1;
long minValue = -maxValue - 1;
for (Number element : elements) {
if ((element.longValue() & bitmask) != 0) {
if (element.longValue() < minValue || element.longValue() > maxValue) {
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;
import java.util.ArrayList;
import java.util.List;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.formats.ArrayPayload;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.util.Preconditions;
import org.junit.Assert;
import org.junit.Test;
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
public void checkArrayPayloadElements() {
int intSize = 4;
int bigNumber = 16843071;
List<Number> numbers = new ArrayList<>();
numbers.add(bigNumber);
verifyArrayPayloadElementIsValid(8, Long.MAX_VALUE);
verifyArrayPayloadElementIsValid(8, Long.MIN_VALUE);
verifyArrayPayloadElementIsValid(4, Integer.MAX_VALUE);
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.
Preconditions.checkArrayPayloadElements(intSize, numbers);
verifyArrayPayloadElementIsInvalid(4, ((long) Integer.MAX_VALUE) + 1);
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);
}
}