fix nil pointer deref when importing a message that the junkfilter could not parse (e.g. malformed header)

import does its own batched junkfilter training, so the deliver function
doesn't have to do it one message at a time, writing the updated filter each
time. however, if the message cannot be parsed, it isn't trained during import,
and deliver would try to train it again. it would try to open the junk filter
to do so, but that would fail because the import function already has the
junkfilter open (and the timeout is reached). a missing error check would
continue with a nil junkfilter, resulting in the nil pointer deref.

this adds the missing error check, and makes sure the deliver function does not
also try to train unparseable imported messages.

report from Jens Hilligsøe
This commit is contained in:
Mechiel Lukkien 2023-02-26 22:21:13 +01:00
parent 7e56ed9e8d
commit 9b3a170cc2
No known key found for this signature in database
2 changed files with 8 additions and 7 deletions

View file

@ -671,15 +671,13 @@ func (a *Account) DeliverX(log *mlog.Log, tx *bstore.Tx, m *Message, msgFile *os
xcheckf(err, "sync directory") xcheckf(err, "sync directory")
} }
if notrain && m.NeedsTraining() { if !notrain && m.NeedsTraining() {
// If this ever happens, hopefully we'll get bug reports about it.
log.Error("deliver of message that unexpectedly needs training", mlog.Field("messageid", m.ID), mlog.Field("trainedjunk", m.TrainedJunk), mlog.Field("flags", m.Flags))
}
l := []Message{*m} l := []Message{*m}
err = a.RetrainMessages(log, tx, l, false) err = a.RetrainMessages(log, tx, l, false)
xcheckf(err, "training junkfilter") xcheckf(err, "training junkfilter")
*m = l[0] *m = l[0]
} }
}
// write contents of r to new file dst, for delivering a message. // write contents of r to new file dst, for delivering a message.
func writeFile(dst string, r io.Reader) error { func writeFile(dst string, r io.Reader) error {

View file

@ -2,6 +2,7 @@ package store
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
@ -63,6 +64,8 @@ func (a *Account) RetrainMessages(log *mlog.Log, tx *bstore.Tx, msgs []Message,
if err != nil && errors.Is(err, ErrNoJunkFilter) { if err != nil && errors.Is(err, ErrNoJunkFilter) {
// No junk filter configured. Nothing more to do. // No junk filter configured. Nothing more to do.
return nil return nil
} else if err != nil {
return fmt.Errorf("open junk filter: %v", err)
} }
defer func() { defer func() {
if jf != nil { if jf != nil {