From 9b3a170cc25224e67989d6a4120f2b6786be56e0 Mon Sep 17 00:00:00 2001 From: Mechiel Lukkien Date: Sun, 26 Feb 2023 22:21:13 +0100 Subject: [PATCH] fix nil pointer deref when importing a message that the junkfilter could not parse (e.g. malformed header) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- store/account.go | 12 +++++------- store/train.go | 3 +++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/store/account.go b/store/account.go index d10f9bc..9dacbe3 100644 --- a/store/account.go +++ b/store/account.go @@ -671,14 +671,12 @@ func (a *Account) DeliverX(log *mlog.Log, tx *bstore.Tx, m *Message, msgFile *os xcheckf(err, "sync directory") } - 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)) + if !notrain && m.NeedsTraining() { + l := []Message{*m} + err = a.RetrainMessages(log, tx, l, false) + xcheckf(err, "training junkfilter") + *m = l[0] } - l := []Message{*m} - err = a.RetrainMessages(log, tx, l, false) - xcheckf(err, "training junkfilter") - *m = l[0] } // write contents of r to new file dst, for delivering a message. diff --git a/store/train.go b/store/train.go index 6c8b980..818e44a 100644 --- a/store/train.go +++ b/store/train.go @@ -2,6 +2,7 @@ package store import ( "errors" + "fmt" "os" "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) { // No junk filter configured. Nothing more to do. return nil + } else if err != nil { + return fmt.Errorf("open junk filter: %v", err) } defer func() { if jf != nil {