78 lines
3 KiB
Markdown
78 lines
3 KiB
Markdown
# UNDF: UNDF-2026-000000399
|
|
# Flutter CWE-407 Scan — CLEAN
|
|
|
|
## Date
|
|
2026-03-27
|
|
|
|
## Scope
|
|
Files fetched and scanned:
|
|
|
|
| File | Lines |
|
|
|------|-------|
|
|
| `packages/flutter/lib/src/widgets/framework.dart` | 7455 |
|
|
| `packages/flutter/lib/src/rendering/object.dart` | 6759 |
|
|
| `packages/flutter/lib/src/widgets/scroll_view.dart` | 2235 |
|
|
| `packages/flutter/lib/src/material/app.dart` | 1271 |
|
|
| `packages/flutter/lib/src/widgets/focus_manager.dart` | 2406 |
|
|
| `packages/flutter/lib/src/widgets/navigator.dart` | 6450 |
|
|
| `packages/flutter/lib/src/widgets/routes.dart` | 2850 |
|
|
| `packages/flutter/lib/src/widgets/focus_traversal.dart` | (fetched) |
|
|
| `packages/flutter/lib/src/gestures/arena.dart` | 304 |
|
|
| `packages/flutter/lib/src/painting/image_cache.dart` | (fetched) |
|
|
| `packages/flutter/lib/src/animation/listener_helpers.dart` | (fetched) |
|
|
| `packages/flutter/lib/src/foundation/observer_list.dart` | (fetched) |
|
|
| `packages/flutter/lib/src/material/theme_data.dart` | 3489 |
|
|
| `packages/flutter/lib/src/rendering/layer.dart` | 3029 |
|
|
|
|
## Findings — All CLEAN
|
|
|
|
### framework.dart
|
|
- `_forgottenChildren`: `HashSet<Element>` — all `.contains()` calls O(1)
|
|
- `_dependencies`: `HashSet<InheritedElement>` — O(1)
|
|
- `_dependents`: `HashMap<Element, Object?>` — O(1)
|
|
- `_InactiveElements._elements`: `HashSet<Element>` — O(1)
|
|
- `forgottenChildren` parameter in `updateChildren()`: `Set<Element>?` — O(1)
|
|
- `_dirtyElements.contains()` at line 2943: inside `assert()` debug string only
|
|
|
|
### rendering/object.dart
|
|
- `usedSemanticsIds`: `Set<int>` passed through — O(1) contains
|
|
|
|
### navigator.dart
|
|
- All key lookups use `Map` (containsKey) — O(1)
|
|
- `phantomEntries.contains()`: type is `Set` — O(1)
|
|
|
|
### focus_manager.dart
|
|
- `_listeners`: `HashedObserverList<VoidCallback>` — O(1) contains (backed by Map)
|
|
- `_statusListeners`: `ObserverList<AnimationStatusListener>` — uses `HashSet`
|
|
cache for lists >= 3 items; O(1) amortised
|
|
- `ancestors`: `List<FocusNode>` cached lazily — `.contains(this)` called once
|
|
(not in a loop) in `hasFocus` getter
|
|
|
|
### focus_traversal.dart
|
|
- `common` set in `_ReadingOrderDirectionalGroupData._textDirectionForList()`:
|
|
`Set<Directionality>` — O(1)
|
|
- `memberAncestors`: builds flat list, no contains calls inside
|
|
|
|
### gesture arena
|
|
- `_arenas.containsKey()`: Map — O(1)
|
|
|
|
### image_cache
|
|
- All containsKey on Maps — O(1)
|
|
|
|
### animation/listener_helpers.dart
|
|
- `_listeners`: `HashedObserverList` — O(1)
|
|
- `_statusListeners`: `ObserverList` with HashSet backing — O(1) amortised
|
|
|
|
### theme_data.dart
|
|
- `extensions.containsKey()`: Map — O(1)
|
|
|
|
### rendering/layer.dart
|
|
- All containsKey/contains calls are on Maps or Rects (geometric contains) — O(1)
|
|
|
|
## Conclusion
|
|
Flutter CLEAN for CWE-407. The Flutter team consistently uses `HashSet`,
|
|
`HashedObserverList`, `HashMap`, and `Set` for all membership tracking in
|
|
production hot paths. No O(N) linear scans were found inside O(N) loops.
|
|
|
|
The one borderline pattern (ObserverList.contains for length < 3) is provably
|
|
O(1) since it only scans up to 2 elements.
|