This is an automated email from the ASF dual-hosted git repository.
wgtmac pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/parquet-java.git
The following commit(s) were added to refs/heads/master by this push:
new 5c360ff5d GH-3659: Throw IAE when dealing with odd-length/invalid hex
string in Parquet CLI (#3642)
5c360ff5d is described below
commit 5c360ff5d879d3567f23cea3290894712fb336d9
Author: Eduard Tudenhoefner <[email protected]>
AuthorDate: Tue Jul 14 10:59:27 2026 +0200
GH-3659: Throw IAE when dealing with odd-length/invalid hex string in
Parquet CLI (#3642)
---
.../java/org/apache/parquet/cli/BaseCommand.java | 13 ++++++++---
.../org/apache/parquet/cli/BaseCommandTest.java | 26 ++++++++++++++++++++++
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/parquet-cli/src/main/java/org/apache/parquet/cli/BaseCommand.java
b/parquet-cli/src/main/java/org/apache/parquet/cli/BaseCommand.java
index 0c8841b05..9e12102e0 100644
--- a/parquet-cli/src/main/java/org/apache/parquet/cli/BaseCommand.java
+++ b/parquet-cli/src/main/java/org/apache/parquet/cli/BaseCommand.java
@@ -20,6 +20,7 @@
package org.apache.parquet.cli;
import com.beust.jcommander.internal.Lists;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
@@ -428,16 +429,22 @@ public abstract class BaseCommand implements Command,
Configurable {
}
}
- private byte[] hexToBytes(String hex) {
-
+ @VisibleForTesting
+ byte[] hexToBytes(String hex) {
+ String originalHex = hex;
if (hex.startsWith("0x") || hex.startsWith("0X")) {
hex = hex.substring(2);
}
int len = hex.length();
+ Preconditions.checkArgument(len % 2 == 0, "Invalid hex string: %s",
originalHex);
+
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
- data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) +
Character.digit(hex.charAt(i + 1), 16));
+ int high = Character.digit(hex.charAt(i), 16);
+ int low = Character.digit(hex.charAt(i + 1), 16);
+ Preconditions.checkArgument(high >= 0 && low >= 0, "Invalid hex string:
%s", originalHex);
+ data[i / 2] = (byte) ((high << 4) + low);
}
return data;
}
diff --git
a/parquet-cli/src/test/java/org/apache/parquet/cli/BaseCommandTest.java
b/parquet-cli/src/test/java/org/apache/parquet/cli/BaseCommandTest.java
index 1f441c334..731f799e1 100644
--- a/parquet-cli/src/test/java/org/apache/parquet/cli/BaseCommandTest.java
+++ b/parquet-cli/src/test/java/org/apache/parquet/cli/BaseCommandTest.java
@@ -18,6 +18,9 @@
*/
package org.apache.parquet.cli;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
import java.io.IOException;
import java.net.URI;
import java.util.List;
@@ -62,6 +65,29 @@ public class BaseCommandTest {
Assert.assertEquals("/a", uri.getPath());
}
+ @Test
+ public void hexToBytes() {
+ assertThat(this.command.hexToBytes("0x10")).containsExactly(0x10);
+ assertThat(this.command.hexToBytes("0x0506")).containsExactly(0x05, 0x06);
+ assertThat(this.command.hexToBytes("0506")).containsExactly(0x05, 0x06);
+ assertThat(this.command.hexToBytes("0x010203")).containsExactly(0x01,
0x02, 0x03);
+ }
+
+ @Test
+ public void hexToBytesRejectsInvalidHexString() {
+ assertThatThrownBy(() -> this.command.hexToBytes("0x011"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Invalid hex string: 0x011");
+
+ assertThatThrownBy(() -> this.command.hexToBytes("0xABZZ"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Invalid hex string: 0xABZZ");
+
+ assertThatThrownBy(() -> this.command.hexToBytes("0xabgg"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Invalid hex string: 0xabgg");
+ }
+
// For Windows
@Test
public void qualifiedPathTestForWindows() throws IOException {