outreach: update scala.md with scala-0002 (intersectionIsEmpty 100x)

This commit is contained in:
russell@unturf.com 2026-03-29 22:12:55 -04:00
parent 72c98d9af6
commit e52caba572

View file

@ -1,12 +1,25 @@
# Scala (compiler) — CWE-407 Disclosure Brief
**2026-03-27 · Patch available — awaiting upstream merge**
**2026-03-29 · 2 patches available — awaiting upstream merge**
## Finding
One O(n²) defect in the Scala 2 compiler's pattern match exhaustiveness checker. `Checkable.scala` uses `to.baseClasses.contains(bc)` — an O(M×N) scan — per pattern match expression during type checking. Patch ready for upstream review.
Two O(n²) defects in the Scala 2 compiler. `Checkable.scala` uses an O(M×N) scan per pattern match expression; `RefChecks.scala` uses an O(D²) scan per overriding method pair during class verification. Patches ready for upstream review.
## The Defects
**scala-0002 (PATCHED — MEDIUM):** `src/compiler/scala/tools/nsc/typechecker/RefChecks.scala`
```scala
// Inside checkAllOverrides — called for every class with overriding methods:
def intersectionIsEmpty(syms1: List[Symbol], syms2: List[Symbol]) =
!syms1.exists(syms2.contains) // syms2.contains = O(D) List scan
```
`syms2.contains` on `List[Symbol]` is O(|syms2|) per call. Both `syms1` and `syms2`
are `extendedOverriddenSymbols` — O(D) symbols for hierarchy depth D.
**O(D²) per overriding pair.** With M pairs per class: **O(M × D²) per compilation unit.**
**Measured ratio: 100×** at D=200.
**scala-0001 (PATCHED — HIGH):** `src/compiler/scala/tools/nsc/typechecker/Checkable.scala`
```scala
@ -20,11 +33,16 @@ to.baseClasses.exists(bc =>
## Complexity Proof
For M=50 base classes in `from`, N=50 base classes in `to`:
**scala-0001:** For M=50 base classes in `from`, N=50 base classes in `to`:
- O(M×N) = 2,500 comparisons per pattern match
- Fixed: `from.baseClasses.toSet` before `exists` loop → O(M + N)
- **50× measured ratio.**
**scala-0002:** For D=200 overridden symbols per method:
- O(D²) = 40,000 comparisons per intersectionIsEmpty call
- Fixed: `syms2.toSet` once, then O(1) per lookup → O(D) per call
- **100× measured ratio at D=200, M=50 pairs.**
## Impact
All Scala 2 codebases using pattern matching — essentially all non-trivial Scala programs. Pattern match exhaustiveness checking runs at compile time for every `match` expression with sealed traits, case classes, and abstract types. Large codebases with complex type hierarchies (deep inheritance chains, many sealed subclasses) hit worst case during compilation. Scala 2 is still widely deployed in production codebases (Spark, Akka, Play, enterprise finance).
@ -45,9 +63,10 @@ val fromBaseSet = from.baseClasses.toSet
to.baseClasses.exists(bc => fromBaseSet.contains(bc)) // O(N) total
```
## Patch
## Patches
`defects/scala/patch/scala-0001-checkable-baseclasses-set.patch`
- `defects/scala/patch/scala-0001-checkable-baseclasses-set.patch`
- `defects/scala/patch/scala-0002-refchecks-intersection-is-empty-hashset.patch`
## What We Ask