amarok, arrow, audacity, cargo, clementine, composer, dask, deluge, dosbox-x, dragonfly. All CWE-407.
3.7 KiB
Dask — CWE-407 Disclosure Brief
2026-04-13 · Patch available — awaiting upstream merge
Finding
Two O(n²) defects in Dask's Parquet partition filter and DataFrame describe aggregation. Both patched. Patches ready for upstream review.
The Defects
dask-project-0001 (PATCHED — MEDIUM-HIGH): dask/dataframe/io/parquet/core.py:558
# In _filter_partitions() — fires during filtered Parquet reads:
for conjunction in disjunction:
for part, stats in zip(*apply_conjunction(parts, statistics, conjunction)):
if part not in out_parts: # list membership — O(O) per partition
out_parts.append(part)
out_statistics.append(stats)
out_parts is a growing list. part not in out_parts is O(O) per partition. With P partitions across multiple OR filter clauses, total cost reaches O(P×O). Large Parquet datasets with many row groups (P=10,000+) and multiple disjunction clauses amplify the cost.
dask-project-0002 (PATCHED — LOW-MEDIUM): dask/dataframe/methods.py:180
# In describe_aggregate() — fires during DataFrame.describe():
names = []
for idxnames in values_indexes:
for name in idxnames:
if name not in names: # list membership — O(N) per name
names.append(name)
names is a growing list. name not in names is O(N) per name. With C total column names across all describe results, total cost reaches O(C²).
Complexity Proof
dask-project-0001: At P=5,000 partitions across disjunctions:
- Defective: 5,000 × 2,500 (avg) = 12,500,000 comparisons
- Fixed: 5,000 × O(1) = 5,000 lookups (set of id())
- ~50× op reduction per filtered Parquet read.
dask-project-0002: At C=500 column names:
- Defective: 500 × 250 (avg) = 125,000 comparisons
- Fixed: 500 × O(1) = 500 lookups (set)
- ~10× op reduction per describe().
Impact
Dask is a parallel computing library for Python analytics — used alongside pandas, scikit-learn, and NumPy for out-of-core and distributed data processing. dask-project-0001 fires on every filtered Parquet read with OR conditions. Data science workflows reading large partitioned Parquet datasets (data lakes, time-series stores, log analytics) with disjunctive filters hit this path.
dask-project-0002 fires during DataFrame.describe() aggregation. Wide DataFrames with many columns amplify the quadratic deduplication.
The Fix
dask-project-0001: Maintain a parallel set of partition identities:
# Before
if part not in out_parts:
# After
# CWE-407 fix: set of id() for O(1) membership instead of O(O) list scan.
out_parts_set = set(id(p) for p in out_parts)
if id(part) not in out_parts_set:
out_parts.append(part)
out_parts_set.add(id(part))
dask-project-0002: Maintain a parallel set for name deduplication:
# Before
if name not in names:
# After
# CWE-407 fix: set for O(1) membership instead of O(N) list scan.
names_set = set()
if name not in names_set:
names.append(name)
names_set.add(name)
Patch
Fix available: defects/dask-project/patch/dask-project-0001.patch and defects/dask-project/patch/dask-project-0002.patch
Two-file patch across parquet/core.py and methods.py.
dask-project-0001: ~50× speedup at P=5,000. dask-project-0002: ~10× speedup at C=500.
What We Ask
A patch is ready for review.
- Confirm receipt and assign an issue reference (dask/dask).
- Assess severity — dask-project-0001 sits on the Parquet I/O hot path and scales with partition count.
- Coordinate a disclosure date — we are targeting 90 days from first contact.
- We will credit the Dask team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.