Conversion.hexTo*() methods now throw IllegalArgumentException instead
of StringIndexOutOfBoundsException
Better exception messages
diff --git a/src/main/java/org/apache/commons/lang3/Conversion.java b/src/main/java/org/apache/commons/lang3/Conversion.java
index 31d9ada..8883907 100644
--- a/src/main/java/org/apache/commons/lang3/Conversion.java
+++ b/src/main/java/org/apache/commons/lang3/Conversion.java
@@ -776,25 +776,25 @@ public static int hexDigitToInt(final char hexDigit) {
}
/**
- * Converts a hexadecimal string into a byte using the default (little-endian, Lsb0) byte and
- * bit ordering.
+ * Converts a hexadecimal string into a byte using the default (little-endian, Lsb0) byte and bit ordering.
*
- * @param src the hexadecimal string to convert
- * @param srcPos the position in {@code src}, in Char unit, from where to start the
- * conversion
- * @param dstInit initial value of the destination byte
- * @param dstPos the position of the LSB, in bits, in the result byte
- * @param nHex the number of Chars to convert
- * @return a byte containing the selected bits
- * @throws IllegalArgumentException if {@code (nHex-1)*4+dstPos >= 8}
+ * @param src the hexadecimal string to convert.
+ * @param srcPos the position in {@code src}, in char unit, from where to start the conversion.
+ * @param dstInit initial value of the destination byte.
+ * @param dstPos the position of the LSB, in bits, in the result byte.
+ * @param nHex the number of Chars to convert.
+ * @return a byte containing the selected bits.
+ * @throws IllegalArgumentException Thrown on invalid input like {@code (nHex - 1) * 4 + dstPos >= 8}.
*/
- public static byte hexToByte(final String src, final int srcPos, final byte dstInit, final int dstPos,
- final int nHex) {
+ public static byte hexToByte(final String src, final int srcPos, final byte dstInit, final int dstPos, final int nHex) {
if (0 == nHex) {
return dstInit;
}
if ((nHex - 1) * 4 + dstPos >= 8) {
- throw new IllegalArgumentException("(nHex-1)*4+dstPos is greater than or equal to 8");
+ throw new IllegalArgumentException("(nHex - 1) * 4 + dstPos is greater than or equal to 8");
+ }
+ if (srcPos + nHex > src.length()) {
+ throw new IllegalArgumentException(String.format("srcPos %,d, + nHex %,d > src.length()", srcPos, nHex, src.length()));
}
byte out = dstInit;
for (int i = 0; i < nHex; i++) {
@@ -811,20 +811,23 @@ public static byte hexToByte(final String src, final int srcPos, final byte dstI
* ordering.
*
* @param src the hexadecimal string to convert
- * @param srcPos the position in {@code src}, in Char unit, from where to start the
+ * @param srcPos the position in {@code src}, in char unit, from where to start the
* conversion
* @param dstInit initial value of the destination int
* @param dstPos the position of the LSB, in bits, in the result int
* @param nHex the number of Chars to convert
* @return an int containing the selected bits
- * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 32}
+ * @throws IllegalArgumentException Thrown on invalid input like {@code (nHex - 1) * 4 + dstPos >= 32}
*/
public static int hexToInt(final String src, final int srcPos, final int dstInit, final int dstPos, final int nHex) {
if (0 == nHex) {
return dstInit;
}
if ((nHex - 1) * 4 + dstPos >= 32) {
- throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 32");
+ throw new IllegalArgumentException("(nHex - 1) * 4 + dstPos is greater or equal to than 32");
+ }
+ if (srcPos + nHex > src.length()) {
+ throw new IllegalArgumentException(String.format("srcPos %,d, + nHex %,d > src.length()", srcPos, nHex, src.length()));
}
int out = dstInit;
for (int i = 0; i < nHex; i++) {
@@ -841,13 +844,13 @@ public static int hexToInt(final String src, final int srcPos, final int dstInit
* bit ordering.
*
* @param src the hexadecimal string to convert
- * @param srcPos the position in {@code src}, in Char unit, from where to start the
+ * @param srcPos the position in {@code src}, in char unit, from where to start the
* conversion
* @param dstInit initial value of the destination long
* @param dstPos the position of the LSB, in bits, in the result long
* @param nHex the number of Chars to convert
* @return a long containing the selected bits
- * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 64}
+ * @throws IllegalArgumentException Thrown on invalid input like {@code (nHex - 1) * 4 + dstPos >= 64}
*/
public static long hexToLong(final String src, final int srcPos, final long dstInit, final int dstPos,
final int nHex) {
@@ -855,7 +858,10 @@ public static long hexToLong(final String src, final int srcPos, final long dstI
return dstInit;
}
if ((nHex - 1) * 4 + dstPos >= 64) {
- throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 64");
+ throw new IllegalArgumentException("(nHex - 1) * 4 + dstPos is greater or equal to than 64");
+ }
+ if (srcPos + nHex > src.length()) {
+ throw new IllegalArgumentException(String.format("srcPos %,d, + nHex %,d > src.length()", srcPos, nHex, src.length()));
}
long out = dstInit;
for (int i = 0; i < nHex; i++) {
@@ -872,13 +878,13 @@ public static long hexToLong(final String src, final int srcPos, final long dstI
* bit ordering.
*
* @param src the hexadecimal string to convert
- * @param srcPos the position in {@code src}, in Char unit, from where to start the
+ * @param srcPos the position in {@code src}, in char unit, from where to start the
* conversion
* @param dstInit initial value of the destination short
* @param dstPos the position of the LSB, in bits, in the result short
* @param nHex the number of Chars to convert
* @return a short containing the selected bits
- * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 16}
+ * @throws IllegalArgumentException Thrown on invalid input like {@code (nHex - 1) * 4 + dstPos >= 16}
*/
public static short hexToShort(final String src, final int srcPos, final short dstInit, final int dstPos,
final int nHex) {
@@ -886,7 +892,10 @@ public static short hexToShort(final String src, final int srcPos, final short d
return dstInit;
}
if ((nHex - 1) * 4 + dstPos >= 16) {
- throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greater or equal to than 16");
+ throw new IllegalArgumentException("(nHex - 1) * 4 + dstPos is greater or equal to than 16");
+ }
+ if (srcPos + nHex > src.length()) {
+ throw new IllegalArgumentException(String.format("srcPos %,d, + nHex %,d > src.length()", srcPos, nHex, src.length()));
}
short out = dstInit;
for (int i = 0; i < nHex; i++) {
diff --git a/src/test/java/org/apache/commons/lang3/ConversionTest.java b/src/test/java/org/apache/commons/lang3/ConversionTest.java
index e147e95..157e128 100644
--- a/src/test/java/org/apache/commons/lang3/ConversionTest.java
+++ b/src/test/java/org/apache/commons/lang3/ConversionTest.java
@@ -16,8 +16,8 @@
*/
package org.apache.commons.lang3;
-import static org.apache.commons.lang3.LangAssertions.assertIndexOutOfBoundsException;
import static org.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
+import static org.apache.commons.lang3.LangAssertions.assertIndexOutOfBoundsException;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -708,6 +708,7 @@ void testHexToByte() {
assertEquals((byte) 0xFD, Conversion.hexToByte(src, 1, (byte) 0, 0, 2));
assertEquals((byte) 0x34, Conversion.hexToByte(src, 0, (byte) 0x34, 0, 0));
assertEquals((byte) 0x84, Conversion.hexToByte(src, 17, (byte) 0x34, 4, 1));
+ assertThrows(IllegalArgumentException.class, () -> Conversion.hexToByte(src, src.length(), (byte) 0, 0, 1));
}
/**
@@ -722,6 +723,7 @@ void testHexToInt() {
assertEquals(0x01C0F1FD, Conversion.hexToInt(src, 1, 0, 0, 8));
assertEquals(0x12345679, Conversion.hexToInt(src, 0, 0x12345679, 0, 0));
assertEquals(0x87645679, Conversion.hexToInt(src, 15, 0x12345679, 20, 3));
+ assertThrows(IllegalArgumentException.class, () -> Conversion.hexToInt(src, src.length(), 0, 0, 1));
}
/**
@@ -734,10 +736,9 @@ void testHexToLong() {
assertEquals(0x000000000000000CL, Conversion.hexToLong(src, 0, 0L, 0, 1));
assertEquals(0x000000001C0F1FDCL, Conversion.hexToLong(src, 0, 0L, 0, 8));
assertEquals(0x0000000001C0F1FDL, Conversion.hexToLong(src, 1, 0L, 0, 8));
- assertEquals(
- 0x123456798ABCDEF0L, Conversion.hexToLong(src, 0, 0x123456798ABCDEF0L, 0, 0));
- assertEquals(
- 0x1234567876BCDEF0L, Conversion.hexToLong(src, 15, 0x123456798ABCDEF0L, 24, 3));
+ assertEquals(0x123456798ABCDEF0L, Conversion.hexToLong(src, 0, 0x123456798ABCDEF0L, 0, 0));
+ assertEquals(0x1234567876BCDEF0L, Conversion.hexToLong(src, 15, 0x123456798ABCDEF0L, 24, 3));
+ assertThrows(IllegalArgumentException.class, () -> Conversion.hexToLong(src, src.length(), 0, 0, 1));
}
/**
@@ -752,6 +753,7 @@ void testHexToShort() {
assertEquals((short) 0xF1FD, Conversion.hexToShort(src, 1, (short) 0, 0, 4));
assertEquals((short) 0x1234, Conversion.hexToShort(src, 0, (short) 0x1234, 0, 0));
assertEquals((short) 0x8764, Conversion.hexToShort(src, 15, (short) 0x1234, 4, 3));
+ assertThrows(IllegalArgumentException.class, () -> Conversion.hexToShort(src, src.length(), (short) 0, 0, 1));
}
/**