From 267944e32b60a165ce596d3dcab398c668e275d4 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Mon, 27 Jul 2026 21:23:19 +0900 Subject: [PATCH] HBASE-30304 Prevent Bytes.toBytesBinary from throwing on truncated \x escape The \xNN parser guards only that the 'x' after a backslash exists, then reads the two hex digits at i+2 and i+3 unconditionally. A string ending in "\x" or "\x0" throws. Widen the guard to require both hex digits in bounds. A truncated tail escape now falls through to the existing bogus-escape path and emits the backslash literally. HBASE-6518 fixed the trailing bare-backslash case with the same guard but did not extend it to the hex digits. --- .../src/main/java/org/apache/hadoop/hbase/util/Bytes.java | 2 +- .../test/java/org/apache/hadoop/hbase/util/BytesTestBase.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java index 96b3dbd4a8a5..8d85076514aa 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/Bytes.java @@ -610,7 +610,7 @@ public static byte[] toBytesBinary(String in) { int size = 0; for (int i = 0; i < in.length(); ++i) { char ch = in.charAt(i); - if (ch == '\\' && in.length() > i + 1 && in.charAt(i + 1) == 'x') { + if (ch == '\\' && in.length() > i + 3 && in.charAt(i + 1) == 'x') { // ok, take next 2 hex digits. char hd1 = in.charAt(i + 2); char hd2 = in.charAt(i + 3); diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/BytesTestBase.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/BytesTestBase.java index 96df8bc39396..31a74d938f46 100644 --- a/hbase-common/src/test/java/org/apache/hadoop/hbase/util/BytesTestBase.java +++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/util/BytesTestBase.java @@ -423,9 +423,11 @@ public void testCopy() { } @Test - public void testToBytesBinaryTrailingBackslashes() { + public void testToBytesBinaryTruncatedHexDigit() { try { Bytes.toBytesBinary("abc\\x00\\x01\\"); + Bytes.toBytesBinary("abc\\x00\\x01\\x"); + Bytes.toBytesBinary("abc\\x00\\x01\\x0"); } catch (StringIndexOutOfBoundsException ex) { fail("Illegal string access: " + ex.getMessage()); }