mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-19 09:50:32 +01:00
VarInt: fix long values accepted as an int value
`-1` and `Integer.MIN_VALUE` (and all values inbetween) are in fact very large VarInts that can only be expressed as a long. So their test data have been moved from `VarIntTest.integerTestVectors` to `longTestVectors`. `intValue()` is changed to guard against such cases, and a helper `fitsInt()` is introduced. JavaDocs are added to `intValue()` and `longValue()` to clarify the expected value ranges.
This commit is contained in:
parent
5f5e7384a2
commit
ba8849ca13
@ -107,12 +107,36 @@ public class VarInt {
|
||||
originallyEncodedSize = copy.originallyEncodedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value as a long. For values greater than {@link Long#MAX_VALUE} the returned long
|
||||
* will be negative. It is still to be interpreted as an unsigned value.
|
||||
*
|
||||
* @return value as a long
|
||||
*/
|
||||
public long longValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public int intValue() {
|
||||
return Math.toIntExact(value);
|
||||
/**
|
||||
* Determine if the value would fit an int, i.e. it is in the range of {@code 0} to {@link Integer#MAX_VALUE}.
|
||||
* If this is true, it's safe to call {@link #intValue()}.
|
||||
*
|
||||
* @return true if the value fits an int, false otherwise
|
||||
*/
|
||||
public boolean fitsInt() {
|
||||
return value >= 0 && value <= Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value as an unsigned int in the range of {@code 0} to {@link Integer#MAX_VALUE}.
|
||||
*
|
||||
* @return value as an unsigned int
|
||||
* @throws ArithmeticException if the value doesn't fit an int
|
||||
*/
|
||||
public int intValue() throws ArithmeticException {
|
||||
check(fitsInt(), () ->
|
||||
new ArithmeticException("value too large for an int: " + Long.toUnsignedString(value)));
|
||||
return (int) value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,6 +26,7 @@ import java.nio.ByteBuffer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(JUnitParamsRunner.class)
|
||||
public class VarIntTest {
|
||||
@ -34,6 +35,7 @@ public class VarIntTest {
|
||||
@Parameters(method = "integerTestVectors")
|
||||
public void testIntCreation(int value, int size) {
|
||||
VarInt a = VarInt.of(value);
|
||||
assertTrue(a.fitsInt());
|
||||
assertEquals(value, a.intValue());
|
||||
assertEquals(size, a.getSizeInBytes());
|
||||
assertEquals(size, a.getOriginalSizeInBytes());
|
||||
@ -45,6 +47,7 @@ public class VarIntTest {
|
||||
@Parameters(method = "longTestVectors")
|
||||
public void testIntGetErr(int value, int size) {
|
||||
VarInt a = VarInt.of(value);
|
||||
assertFalse(a.fitsInt());
|
||||
a.intValue();
|
||||
}
|
||||
|
||||
@ -52,6 +55,7 @@ public class VarIntTest {
|
||||
@Parameters(method = "longTestVectors")
|
||||
public void testIntGetErr2(int value, int size) {
|
||||
VarInt a = VarInt.of(value);
|
||||
assertFalse(a.fitsInt());
|
||||
VarInt.ofBytes(a.serialize(), 0).intValue();
|
||||
}
|
||||
|
||||
@ -89,10 +93,7 @@ public class VarIntTest {
|
||||
new Object[]{ 0x7FFF, 3},
|
||||
new Object[]{ 0x8000, 3},
|
||||
new Object[]{ 0x10000, 5},
|
||||
new Object[]{ Integer.MIN_VALUE, 9},
|
||||
new Object[]{ Integer.MAX_VALUE, 5},
|
||||
// -1 shouldn't normally be passed, but at least stay consistent (bug regression test)
|
||||
new Object[]{ -1, 9}
|
||||
};
|
||||
}
|
||||
|
||||
@ -105,9 +106,9 @@ public class VarIntTest {
|
||||
new Object[]{ 0xAABBCCDDL, 5},
|
||||
new Object[]{ 0xFFFFFFFFL, 5},
|
||||
new Object[]{ 0xCAFEBABEDEADBEEFL, 9},
|
||||
new Object[]{ Integer.MIN_VALUE, 9},
|
||||
new Object[]{ Long.MIN_VALUE, 9},
|
||||
new Object[]{ Long.MAX_VALUE, 9},
|
||||
// -1 shouldn't normally be passed, but at least stay consistent (bug regression test)
|
||||
new Object[]{ -1L, 9}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user