24 lines
1.1 KiB
Markdown
24 lines
1.1 KiB
Markdown
# dendrite-0001: CWE-407 in dendrite — syncapi storage WriteEvent prevEvents O(P²) double loop
|
||
|
||
**Severity:** HIGH
|
||
**File:** `syncapi/storage/shared/storage_consumer.go:243`
|
||
**Pattern:**
|
||
```go
|
||
prevEvents, err := d.OutputEvents.SelectEvents(ctx, txn, ev.PrevEventIDs(), nil, false)
|
||
// ...
|
||
for _, eID := range ev.PrevEventIDs() { // O(P) prev event IDs
|
||
found = false
|
||
for _, prevEv := range prevEvents { // O(E) events returned from DB
|
||
if eID == prevEv.EventID() { // O(1) string comparison
|
||
found = true
|
||
}
|
||
}
|
||
if !found {
|
||
// insert backward extremity
|
||
}
|
||
}
|
||
```
|
||
**Complexity:** O(P × E) — nested loops over prev event IDs and fetched events, run on every event written to sync storage
|
||
**Fix:** Build a `map[string]bool` from `prevEvents` before the outer loop: `prevEventSet[prevEv.EventID()] = true`, then `if !prevEventSet[eID]`
|
||
**Speedup:** 50–200× for P=E=50 (federation bursts with many prev events)
|
||
**Hot path:** `WriteEvent()` — called for every event written to sync API storage (all Matrix room traffic)
|