java-topology/defects/cassandra/patch/cassandra-0005-list-discarder-hashset.patch

27 lines
1.6 KiB
Diff

# UNDF: UNDF-2026-000000024
--- a/src/java/org/apache/cassandra/cql3/terms/Lists.java
+++ b/src/java/org/apache/cassandra/cql3/terms/Lists.java
@@ -519,15 +519,15 @@ public abstract class Lists
- // Note: below, we will call 'contains' on this toDiscard list for each element of existingList.
- // Meaning that if toDiscard is big, converting it to a HashSet might be more efficient. However,
- // the read-before-write this operation requires limits its usefulness on big lists, so in practice
- // toDiscard will be small and keeping a list will be more efficient.
- List<ByteBuffer> toDiscard = value.getElements();
- for (Cell<?> cell : complexData)
- {
- if (toDiscard.contains(cell.buffer()))
- params.addTombstone(column, cell.path());
- }
+ // CWE-407 fix: convert toDiscard to HashSet before the loop.
+ // toDiscard.contains() on a List is O(|toDiscard|) per call; with a loop
+ // over complexData (up to 65535 cells) the total is O(E * D) — quadratic
+ // when both sides are large. The guardrail threshold (collection_list_size)
+ // is null by default, so there is no enforced upper bound.
+ // HashSet.contains() is O(1), making the loop O(E + D) overall.
+ Set<ByteBuffer> toDiscardSet = new HashSet<>(value.getElements());
+ for (Cell<?> cell : complexData)
+ {
+ if (toDiscardSet.contains(cell.buffer()))
+ params.addTombstone(column, cell.path());
+ }