justinmclean opened a new issue, #10165:
URL: https://github.com/apache/gravitino/issues/10165
### What would you like to be improved?
LancePartitionStatisticStorage.dropStatisticsImpl(...) builds
dataset.delete(...) filter strings by concatenating raw partitionName and
statisticNames into SQL literals. If a value contains a single quote (for
example, partition'01), the generated filter is invalid and deletion fails;
crafted input can also broaden the deletion scope.
### How should we improve?
Sanitize all string literals before embedding in filter SQL, at minimum by
escaping single quotes (' -> '') for:
- partition_name = '...'
- each item in statistic_name IN ('...')
Prefer a small helper like escapeSqlLiteral(String) and use it consistently
in dropStatisticsImpl (and any similar filter builders).
Here's a unit test to help:
```
public class TestLancePartitionStatisticStorageSqlEscapeBug {
@Test
public void testDropStatisticsWithQuoteInPartitionName() throws Exception {
PartitionStatisticStorageFactory factory = new
LancePartitionStatisticStorageFactory();
String metalakeName = "metalake";
MetadataObject metadataObject =
MetadataObjects.of(Lists.newArrayList("catalog", "schema", "table"),
MetadataObject.Type.TABLE);
EntityStore entityStore = mock(EntityStore.class);
TableEntity tableEntity = mock(TableEntity.class);
when(entityStore.get(any(), any(), any())).thenReturn(tableEntity);
when(tableEntity.id()).thenReturn(1L);
FieldUtils.writeField(GravitinoEnv.getInstance(), "entityStore",
entityStore, true);
String location =
Files.createTempDirectory("lance_stats_test_quote").toString();
Map<String, String> properties = Maps.newHashMap();
properties.put("location", location);
LancePartitionStatisticStorage storage =
(LancePartitionStatisticStorage) factory.create(properties);
try {
String quotedPartition = "partition'01";
Map<String, StatisticValue<?>> stats = Maps.newHashMap();
stats.put("statistic0", StatisticValues.stringValue("value0"));
storage.updateStatistics(
metalakeName,
Lists.newArrayList(
MetadataObjectStatisticsUpdate.of(
metadataObject,
Lists.newArrayList(
PartitionStatisticsModification.update(quotedPartition, stats)))));
PartitionStatisticsDrop drop =
PartitionStatisticsModification.drop(quotedPartition,
Lists.newArrayList("statistic0"));
Assertions.assertDoesNotThrow(
() ->
storage.dropStatistics(
metalakeName,
Lists.newArrayList(
MetadataObjectStatisticsDrop.of(metadataObject,
Lists.newArrayList(drop)))));
} finally {
FileUtils.deleteDirectory(new File(location + "/" + tableEntity.id() +
".lance"));
storage.close();
}
}
}
```
You'll likley need to run ./gradlew :core:spotlessApply to correctly format
this.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]