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;
|
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() {
|
public long longValue() {
|
||||||
return value;
|
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.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@RunWith(JUnitParamsRunner.class)
|
@RunWith(JUnitParamsRunner.class)
|
||||||
public class VarIntTest {
|
public class VarIntTest {
|
||||||
@ -34,6 +35,7 @@ public class VarIntTest {
|
|||||||
@Parameters(method = "integerTestVectors")
|
@Parameters(method = "integerTestVectors")
|
||||||
public void testIntCreation(int value, int size) {
|
public void testIntCreation(int value, int size) {
|
||||||
VarInt a = VarInt.of(value);
|
VarInt a = VarInt.of(value);
|
||||||
|
assertTrue(a.fitsInt());
|
||||||
assertEquals(value, a.intValue());
|
assertEquals(value, a.intValue());
|
||||||
assertEquals(size, a.getSizeInBytes());
|
assertEquals(size, a.getSizeInBytes());
|
||||||
assertEquals(size, a.getOriginalSizeInBytes());
|
assertEquals(size, a.getOriginalSizeInBytes());
|
||||||
@ -45,6 +47,7 @@ public class VarIntTest {
|
|||||||
@Parameters(method = "longTestVectors")
|
@Parameters(method = "longTestVectors")
|
||||||
public void testIntGetErr(int value, int size) {
|
public void testIntGetErr(int value, int size) {
|
||||||
VarInt a = VarInt.of(value);
|
VarInt a = VarInt.of(value);
|
||||||
|
assertFalse(a.fitsInt());
|
||||||
a.intValue();
|
a.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +55,7 @@ public class VarIntTest {
|
|||||||
@Parameters(method = "longTestVectors")
|
@Parameters(method = "longTestVectors")
|
||||||
public void testIntGetErr2(int value, int size) {
|
public void testIntGetErr2(int value, int size) {
|
||||||
VarInt a = VarInt.of(value);
|
VarInt a = VarInt.of(value);
|
||||||
|
assertFalse(a.fitsInt());
|
||||||
VarInt.ofBytes(a.serialize(), 0).intValue();
|
VarInt.ofBytes(a.serialize(), 0).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +93,7 @@ public class VarIntTest {
|
|||||||
new Object[]{ 0x7FFF, 3},
|
new Object[]{ 0x7FFF, 3},
|
||||||
new Object[]{ 0x8000, 3},
|
new Object[]{ 0x8000, 3},
|
||||||
new Object[]{ 0x10000, 5},
|
new Object[]{ 0x10000, 5},
|
||||||
new Object[]{ Integer.MIN_VALUE, 9},
|
|
||||||
new Object[]{ Integer.MAX_VALUE, 5},
|
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[]{ 0xAABBCCDDL, 5},
|
||||||
new Object[]{ 0xFFFFFFFFL, 5},
|
new Object[]{ 0xFFFFFFFFL, 5},
|
||||||
new Object[]{ 0xCAFEBABEDEADBEEFL, 9},
|
new Object[]{ 0xCAFEBABEDEADBEEFL, 9},
|
||||||
|
new Object[]{ Integer.MIN_VALUE, 9},
|
||||||
new Object[]{ Long.MIN_VALUE, 9},
|
new Object[]{ Long.MIN_VALUE, 9},
|
||||||
new Object[]{ Long.MAX_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}
|
new Object[]{ -1L, 9}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user