Mail-Graveyard/bug-mbox-reader.md
2026-07-15 00:57:16 +02:00

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

  1. Unit-Test, der genau das faengt: mbox mit 3 unterschiedlich langen Mails schreiben, dann readMboxMessagesBytes aufrufen und pruefen, dass msgs[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.)
  2. 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, was mbox_index fuer diese seq sagt.
  3. Ich (Claude) fahre den Sweep ueber alle 678 Indizes von colak gegen mbox_index0 Abweichungen ist die Latte.