You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ho...@apache.org on 2026/09/25 19:40:24 UTC

(spark) branch branch-3.5 updated: [MINOR][3.5][CORE] Avoid accidental collisions in SHS using LevelDB

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch branch-3.5
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/branch-3.5 by this push:
     new 70be7f54ef66 [MINOR][3.5][CORE] Avoid accidental collisions in SHS using LevelDB
70be7f54ef66 is described below

commit 70be7f54ef669892d51271337e2019b98d611212
Author: Holden Karau <ho...@pigscanfly.ca>
AuthorDate: Fri Sep 25 12:40:13 2026 -0700

    [MINOR][3.5][CORE] Avoid accidental collisions in SHS using LevelDB
    
    String index values are copied verbatim into store keys, so an embedded key separator (0x00) corrupts the index key structure and mixes entries across range scans and deletes. Fail fast with IllegalArgumentException in LevelDBTypeInfo and RocksDBTypeInfo instead.
    
    This is a backport of 23fdef7dd37aa1a10b132cf5bfd56a06141384f5
    
    Closes #58616 from holdenk/111-kvstore-index-validation-branch-3.5.
    
    Lead-authored-by: Holden Karau <ho...@pigscanfly.ca>
    Co-authored-by: Holden Karau <ho...@snowflake.com>
    Signed-off-by: Holden Karau <ho...@snowflake.com>
---
 .../main/java/org/apache/spark/util/kvstore/LevelDBTypeInfo.java | 9 +++++++++
 .../main/java/org/apache/spark/util/kvstore/RocksDBTypeInfo.java | 9 +++++++++
 .../java/org/apache/spark/util/kvstore/LevelDBTypeInfoSuite.java | 8 ++++++++
 .../java/org/apache/spark/util/kvstore/RocksDBTypeInfoSuite.java | 8 ++++++++
 4 files changed, 34 insertions(+)

diff --git a/common/kvstore/src/main/java/org/apache/spark/util/kvstore/LevelDBTypeInfo.java b/common/kvstore/src/main/java/org/apache/spark/util/kvstore/LevelDBTypeInfo.java
index 4d7f76f67386..d313dcd6c779 100644
--- a/common/kvstore/src/main/java/org/apache/spark/util/kvstore/LevelDBTypeInfo.java
+++ b/common/kvstore/src/main/java/org/apache/spark/util/kvstore/LevelDBTypeInfo.java
@@ -461,6 +461,15 @@ class LevelDBTypeInfo {
 
       if (value instanceof String) {
         byte[] str = ((String) value).getBytes(UTF_8);
+        for (byte b : str) {
+          if (b == KEY_SEPARATOR) {
+            // String bytes are copied verbatim into the key, so an embedded key
+            // separator would corrupt the index key structure and mix entries across
+            // range scans and deletes. Reject such values outright.
+            throw new IllegalArgumentException(
+              "Index string values cannot contain the key separator (0x00) byte.");
+          }
+        }
         result = new byte[str.length + 1];
         result[0] = prefix;
         System.arraycopy(str, 0, result, 1, str.length);
diff --git a/common/kvstore/src/main/java/org/apache/spark/util/kvstore/RocksDBTypeInfo.java b/common/kvstore/src/main/java/org/apache/spark/util/kvstore/RocksDBTypeInfo.java
index c5452b4104ba..525051257dc8 100644
--- a/common/kvstore/src/main/java/org/apache/spark/util/kvstore/RocksDBTypeInfo.java
+++ b/common/kvstore/src/main/java/org/apache/spark/util/kvstore/RocksDBTypeInfo.java
@@ -463,6 +463,15 @@ class RocksDBTypeInfo {
 
       if (value instanceof String) {
         byte[] str = ((String) value).getBytes(UTF_8);
+        for (byte b : str) {
+          if (b == KEY_SEPARATOR) {
+            // String bytes are copied verbatim into the key, so an embedded key
+            // separator would corrupt the index key structure and mix entries across
+            // range scans and deletes. Reject such values outright.
+            throw new IllegalArgumentException(
+              "Index string values cannot contain the key separator (0x00) byte.");
+          }
+        }
         result = new byte[str.length + 1];
         result[0] = prefix;
         System.arraycopy(str, 0, result, 1, str.length);
diff --git a/common/kvstore/src/test/java/org/apache/spark/util/kvstore/LevelDBTypeInfoSuite.java b/common/kvstore/src/test/java/org/apache/spark/util/kvstore/LevelDBTypeInfoSuite.java
index 0359e11404cd..ae269076f4ce 100644
--- a/common/kvstore/src/test/java/org/apache/spark/util/kvstore/LevelDBTypeInfoSuite.java
+++ b/common/kvstore/src/test/java/org/apache/spark/util/kvstore/LevelDBTypeInfoSuite.java
@@ -210,4 +210,12 @@ public class LevelDBTypeInfoSuite {
 
   }
 
+
+  @Test
+  public void testStringValuesRejectKeySeparator() throws Exception {
+    LevelDBTypeInfo.Index idx = newTypeInfo(CustomType1.class).indices().iterator().next();
+    assertThrows(IllegalArgumentException.class, () -> idx.toKey("key\u0000suffix"));
+    assertThrows(IllegalArgumentException.class,
+      () -> idx.toKey(new String[] { "ok", "bad\u0000" }));
+  }
 }
diff --git a/common/kvstore/src/test/java/org/apache/spark/util/kvstore/RocksDBTypeInfoSuite.java b/common/kvstore/src/test/java/org/apache/spark/util/kvstore/RocksDBTypeInfoSuite.java
index f694fd36b68b..5b606cc60145 100644
--- a/common/kvstore/src/test/java/org/apache/spark/util/kvstore/RocksDBTypeInfoSuite.java
+++ b/common/kvstore/src/test/java/org/apache/spark/util/kvstore/RocksDBTypeInfoSuite.java
@@ -210,4 +210,12 @@ public class RocksDBTypeInfoSuite {
 
   }
 
+
+  @Test
+  public void testStringValuesRejectKeySeparator() throws Exception {
+    RocksDBTypeInfo.Index idx = newTypeInfo(CustomType1.class).indices().iterator().next();
+    assertThrows(IllegalArgumentException.class, () -> idx.toKey("key\u0000suffix"));
+    assertThrows(IllegalArgumentException.class,
+      () -> idx.toKey(new String[] { "ok", "bad\u0000" }));
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org