3.9 KiB
🔴 KRITISCH — mbox-Leser liefert falsche Mails (Buffer-Aliasing)
Schweregrad: hoch. Der Leser gibt fuer fast jeden Index dieselbe (falsche) Mail zurueck. Betrifft Vorschau, manuelles Verschieben, Archiv-Export und Archiv-Dedup.
Entwarnung vorweg: Die Archiv-Dateien auf der Platte sind korrekt. Der
Schreiber ist ein anderer Pfad und haengt die Rohbytes richtig an. Geprueft:
In colak@dr-gold.de/INBOX.mbox steht an Position 537 exakt das, was
mbox_index sagt. Kaputt ist ausschliesslich der Leser. Es sind keine Daten
verloren.
Die Ursache — eine Zeile
backend/06-mbox.go:441, readMboxMessagesBytes:
if inMsg && cur.Len() > 0 {
msgs = append(msgs, bytes.TrimRight(cur.Bytes(), "\n")) // Slice ZEIGT IN cur's Puffer
cur.Reset() // Puffer wird wiederverwendet
}
bytes.Buffer.Bytes() liefert keine Kopie, sondern einen Slice in den
internen Puffer. Direkt danach cur.Reset() — der Puffer wird fuer die
naechste Mail ueberschrieben. Alle zuvor angehaengten Slices zeigen auf
denselben Speicher und tragen am Ende den zuletzt geschriebenen Inhalt.
Der Lehrbuchfehler „Buffer.Bytes() + Reset() ohne Kopie".
Der Fix
if inMsg && cur.Len() > 0 {
trimmed := bytes.TrimRight(cur.Bytes(), "\n")
msg := make([]byte, len(trimmed))
copy(msg, trimmed) // <-- ECHTE Kopie
msgs = append(msgs, msg)
cur.Reset()
}
(Dasselbe fuer den Abschluss nach der Schleife, falls dort ebenfalls
cur.Bytes() ohne Kopie angehaengt wird — bitte pruefen.)
Besser noch: bytes.Buffer ganz vermeiden und die Nachrichten ueber
Byte-Offsets aus dem Original-Slice schneiden (b[start:end]) — dann gibt es
kein Aliasing-Risiko und keine Kopie zu viel.
Reproduktion (gemessen an colak@dr-gold.de / INBOX, 678 Mails)
idx | mbox_index sagt | Vorschau liefert
0 | Katalogseite | Angebot: CARRYMATE Transportgriffe FALSCH
1 | Angebot: CARRYMATE Transportgriffe | Baustoff + Metall FALSCH
2 | Schoenes Wochenende | Baustoff + Metall FALSCH
3 | Bestellung '150129' | Baustoff + Metall FALSCH
...
15 | Per E-Mail senden: Bestellschein.doc| Baustoff + Metall FALSCH
Ab Index 1 kommt immer dieselbe Mail zurueck. Die Liste und
mbox_index stimmen ueberein — nur der Leser luegt.
Blast Radius — bitte alle pruefen
ReadMboxMessage / readMboxMessages haengen an:
| Stelle | Wirkung des Bugs |
|---|---|
08-viewer.go:51 |
Vorschau zeigt die falsche Mail |
08-viewer.go:83, :335 |
dito (Ziel-/Transfer-Vorschau) |
08-viewer.go:489 |
manuelles Verschieben → schreibt die falsche Mail in ein echtes Ziel-Postfach |
08-viewer.go:599 |
Suche liefert falsche Treffer |
00-router.go:1320 |
Transfer-Vorschau |
12-archive-tools.go:291, :332 |
Archiv-Export (ZIP) und Archiv-Dedup → Export koennte falsche Mails enthalten, Dedup koennte die falschen loeschen |
Wichtig: Falls /archives/dedup oder das manuelle Verschieben schon benutzt
wurden, muss geprueft werden, ob dabei Schaden entstanden ist.
Abnahme
- Unit-Test, der genau das faengt: mbox mit 3 unterschiedlich langen Mails
schreiben, dann
readMboxMessagesBytesaufrufen und pruefen, dassmsgs[0] != msgs[1] != msgs[2]und jede den erwarteten Betreff hat. (Ein Test mit gleich langen Mails wuerde den Bug NICHT finden — deshalb unterschiedliche Laengen, damit der Puffer waechst.) - Live:
/view?account=colak@dr-gold.de&folder=INBOX, dann fuer die Indizes 0, 1, 2, 300, 677 die Vorschau abrufen → Betreff und Datum muessen exakt dem entsprechen, wasmbox_indexfuer dieseseqsagt. - Ich (Claude) fahre den Sweep ueber alle 678 Indizes von colak gegen
mbox_index— 0 Abweichungen ist die Latte.