From 3b90b3b0ddfd8134daa1d417bdd7acd8c39781b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ensar=20Saraj=C4=8Di=C4=87?= Date: Fri, 22 Jul 2022 08:39:39 +0200 Subject: [PATCH] fix: crash when copying/moving all messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prevents dereferencing nil when updating RUE counts. This seems to happen for messages that were not yet loaded, but were selected for copy operation. This can happen when using `mark -a` command and then initiating copy operation. When such message is encountered during RUE counting, it is stopped and full recount is triggered. **Original backtrace:** Error: runtime error: invalid memory address or nil pointer dereference goroutine 1 [running]: runtime/debug.Stack() runtime/debug/stack.go:24 +0x65 git.sr.ht/~rjarry/aerc/logging.PanicHandler() git.sr.ht/~rjarry/aerc/logging/panic-logger.go:45 +0x64b panic({0x9e5f80, 0xecc360}) runtime/panic.go:844 +0x258 git.sr.ht/~rjarry/aerc/widgets.(*AccountView).onMessage(0xc0001be870, {0xb7f860?, 0xc00073b4c0?}) git.sr.ht/~rjarry/aerc/widgets/account.go:353 +0xecc git.sr.ht/~rjarry/aerc/widgets.(*AccountView).Tick(0xc0001be870) git.sr.ht/~rjarry/aerc/widgets/account.go:116 +0x6c git.sr.ht/~rjarry/aerc/widgets.(*Aerc).Tick(0xc0003ba000) git.sr.ht/~rjarry/aerc/widgets/aerc.go:144 +0x7a main.main() git.sr.ht/~rjarry/aerc/aerc.go:225 +0xbb8 Signed-off-by: Ensar Sarajčić Acked-by: Robin Jarry --- widgets/account.go | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/widgets/account.go b/widgets/account.go index 93a277d..3172a30 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -334,12 +334,18 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { // Only update the destination destStore if it is initialized if destStore, ok := acct.dirlist.MsgStore(msg.Destination); ok { var recent, unseen int + var accurate bool = true for _, uid := range msg.Uids { // Get the message from the originating store msg, ok := acct.Store().Messages[uid] if !ok { continue } + // If message that was not yet loaded is copied + if msg == nil { + accurate = false + break + } seen := false for _, flag := range msg.Flags { if flag == models.SeenFlag { @@ -353,13 +359,19 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { unseen = unseen + 1 } } - destStore.DirInfo.Recent += recent - destStore.DirInfo.Unseen += unseen - destStore.DirInfo.Exists += len(msg.Uids) - // True. For imap, we don't have the message in the store until we - // Select so we need to rely on the math we just did for accurate - // counts - destStore.DirInfo.AccurateCounts = true + if accurate { + destStore.DirInfo.Recent += recent + destStore.DirInfo.Unseen += unseen + destStore.DirInfo.Exists += len(msg.Uids) + // True. For imap, we don't have the message in the store until we + // Select so we need to rely on the math we just did for accurate + // counts + destStore.DirInfo.AccurateCounts = true + } else { + destStore.DirInfo.Exists += len(msg.Uids) + // False to trigger recount of recent/unseen + destStore.DirInfo.AccurateCounts = false + } } case *types.LabelList: acct.labels = msg.Labels