This is an automated email from the ASF dual-hosted git repository.
yuqi1129 pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new c50209ff36 [Cherry-pick to branch-1.3] [#13189] fix(lance): reject
empty storage option keys (#13190) (#13284)
c50209ff36 is described below
commit c50209ff36878cc78fe89a86a03f0c36b3d42997
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Sep 18 09:09:56 2026 +0800
[Cherry-pick to branch-1.3] [#13189] fix(lance): reject empty storage
option keys (#13190) (#13284)
**Cherry-pick Information:**
- Original commit: eca1b1a4474f53778fd6458be606f603d965a453
- Target branch: `branch-1.3`
- Status: ✅ Clean cherry-pick (no conflicts)
Signed-off-by: jiangxt2 <[email protected]>
Co-authored-by: StormSpirit <[email protected]>
Co-authored-by: Qi Yu <[email protected]>
---
.../lance/common/utils/LancePropertiesUtils.java | 11 ++++++++-
.../common/utils/TestLancePropertiesUtils.java | 26 +++++++++++++++++++++-
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git
a/lance/lance-common/src/main/java/org/apache/gravitino/lance/common/utils/LancePropertiesUtils.java
b/lance/lance-common/src/main/java/org/apache/gravitino/lance/common/utils/LancePropertiesUtils.java
index 39fbe93bf4..4d235afcf8 100644
---
a/lance/lance-common/src/main/java/org/apache/gravitino/lance/common/utils/LancePropertiesUtils.java
+++
b/lance/lance-common/src/main/java/org/apache/gravitino/lance/common/utils/LancePropertiesUtils.java
@@ -21,6 +21,7 @@ package org.apache.gravitino.lance.common.utils;
import static
org.apache.gravitino.lance.common.utils.LanceConstants.LANCE_STORAGE_OPTIONS_PREFIX;
+import com.google.common.base.Preconditions;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
@@ -37,6 +38,7 @@ public final class LancePropertiesUtils {
*
* @param tableProperties the source properties
* @return the Lance storage options without the `lance.storage.` prefix
+ * @throws IllegalArgumentException if a property key is exactly
`lance.storage.`
*/
public static Map<String, String> getLanceStorageOptions(Map<String, String>
tableProperties) {
if (tableProperties == null || tableProperties.isEmpty()) {
@@ -47,7 +49,14 @@ public final class LancePropertiesUtils {
.filter(entry ->
entry.getKey().startsWith(LANCE_STORAGE_OPTIONS_PREFIX))
.collect(
Collectors.toMap(
- entry ->
entry.getKey().substring(LANCE_STORAGE_OPTIONS_PREFIX.length()),
+ entry -> {
+ String propertyKey = entry.getKey();
+ Preconditions.checkArgument(
+ !LANCE_STORAGE_OPTIONS_PREFIX.equals(propertyKey),
+ "Lance storage option key cannot be empty: %s",
+ propertyKey);
+ return
propertyKey.substring(LANCE_STORAGE_OPTIONS_PREFIX.length());
+ },
Map.Entry::getValue,
(left, right) -> right,
LinkedHashMap::new));
diff --git
a/lance/lance-common/src/test/java/org/apache/gravitino/lance/common/utils/TestLancePropertiesUtils.java
b/lance/lance-common/src/test/java/org/apache/gravitino/lance/common/utils/TestLancePropertiesUtils.java
index 55bfa6c347..51de5b37e1 100644
---
a/lance/lance-common/src/test/java/org/apache/gravitino/lance/common/utils/TestLancePropertiesUtils.java
+++
b/lance/lance-common/src/test/java/org/apache/gravitino/lance/common/utils/TestLancePropertiesUtils.java
@@ -19,6 +19,8 @@
package org.apache.gravitino.lance.common.utils;
import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -31,14 +33,34 @@ public class TestLancePropertiesUtils {
ImmutableMap.of(
"lance.storage.endpoint", "http://minio:9000",
"lance.storage.access_key_id", "ak",
+ "lance.storage.s3.custom_option", "custom-value",
"not.storage.key", "ignored");
Map<String, String> storageOptions =
LancePropertiesUtils.getLanceStorageOptions(properties);
- Assertions.assertEquals(2, storageOptions.size());
+ Assertions.assertEquals(3, storageOptions.size());
Assertions.assertEquals("http://minio:9000",
storageOptions.get("endpoint"));
Assertions.assertEquals("ak", storageOptions.get("access_key_id"));
+ Assertions.assertEquals("custom-value",
storageOptions.get("s3.custom_option"));
Assertions.assertFalse(storageOptions.containsKey("not.storage.key"));
+ Assertions.assertEquals(
+ List.of("endpoint", "access_key_id", "s3.custom_option"),
+ new ArrayList<>(storageOptions.keySet()));
+ }
+
+ /** Verifies that the storage prefix itself cannot become an empty provider
option key. */
+ @Test
+ public void testGetLanceStorageOptionsRejectsEmptyOptionKey() {
+ String propertyValue = "secret-value-must-not-leak";
+ IllegalArgumentException exception =
+ Assertions.assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ LancePropertiesUtils.getLanceStorageOptions(
+ Map.of("lance.storage.", propertyValue)));
+
+ Assertions.assertTrue(exception.getMessage().contains("lance.storage."));
+ Assertions.assertFalse(exception.getMessage().contains(propertyValue));
}
@Test
@@ -59,5 +81,7 @@ public class TestLancePropertiesUtils {
Assertions.assertEquals("http://table:9000",
storageOptions.get("endpoint"));
Assertions.assertEquals("us-east-1", storageOptions.get("region"));
Assertions.assertEquals("table-ak", storageOptions.get("access_key_id"));
+ Assertions.assertEquals(
+ List.of("endpoint", "region", "access_key_id"), new
ArrayList<>(storageOptions.keySet()));
}
}