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 {

Reply via email to