about summary refs log tree commit diff stats
path: root/lib/msgstore.go
diff options
context:
space:
mode:
authorKiril Vladimiroff <kiril@vladimiroff.org>2019-12-10 22:07:01 +0200
committerDrew DeVault <sir@cmpwn.com>2019-12-12 12:29:39 -0500
commitd9a0522780cab5b51b2c18e64ce8c9df764c8313 (patch)
tree2e438d117ef872d68ca380f91ec88d1ba0dee09f /lib/msgstore.go
parent0ef4b6f9e2810e5316c71d27db230925b483732e (diff)
downloadaerc-d9a0522780cab5b51b2c18e64ce8c9df764c8313.tar.gz
Break early when delete happens in outdated state
A panic could happen when multiple delete messages are sent one after
another without waiting until there are no messages left to be deleted:

	panic: runtime error: makeslice: len out of range

	goroutine 1 [running]:
	git.sr.ht/~sircmpwn/aerc/lib.(*MessageStore).Update(0xc000592e00, 0xa8fe60, 0xc0003340f0)
		/go/src/git.sr.ht/~sircmpwn/aerc/lib/msgstore.go:222 +0x5b8
	git.sr.ht/~sircmpwn/aerc/widgets.(*AccountView).onMessage(0xc0000a0460, 0xa8fe60, 0xc0003340f0)
		/go/src/git.sr.ht/~sircmpwn/aerc/widgets/account.go:251 +0x307
	git.sr.ht/~sircmpwn/aerc/widgets.(*AccountView).Tick(0xc0000a0460, 0xc0001496b0)
		/go/src/git.sr.ht/~sircmpwn/aerc/widgets/account.go:90 +0xa1
	git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Tick(0xc0000a9f40, 0xc000020501)
		/go/src/git.sr.ht/~sircmpwn/aerc/widgets/aerc.go:123 +0x91
	main.main()
		/go/src/git.sr.ht/~sircmpwn/aerc/aerc.go:182 +0x5bf

The make that blows up is:

	uids := make([]uint32, len(store.uids)-len(msg.Uids))

This change simply checks whether the make is going to be valid before
starting to work on the actual delete. If there are more messages queued
to be deleted than what's left in the store, then we're obviously in an
inconsistent state, ask for an update and break.
Diffstat (limited to 'lib/msgstore.go')
-rw-r--r--lib/msgstore.go5
1 files changed, 5 insertions, 0 deletions
diff --git a/lib/msgstore.go b/lib/msgstore.go
index 434e0ad..2a9ea86 100644
--- a/lib/msgstore.go
+++ b/lib/msgstore.go
@@ -213,6 +213,11 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
 			}
 		}
 	case *types.MessagesDeleted:
+		if len(store.uids) < len(msg.Uids) {
+			update = true
+			break
+		}
+
 		toDelete := make(map[uint32]interface{})
 		for _, uid := range msg.Uids {
 			toDelete[uid] = nil