compose: prevent out of bounds access
Fix the following panic, seen while switching accounts: runtime error: index out of range [4] with length 4 goroutine 6 [running]: git.sr.ht/~rjarry/aerc/widgets.(*Composer).Focus(0xc005cfbe30?, 0x40?) git.sr.ht/~rjarry/aerc/widgets/compose.go:618 +0x51 git.sr.ht/~rjarry/aerc/widgets.(*Aerc).focus(0xc00034c000, {0x0?, 0x0}) git.sr.ht/~rjarry/aerc/widgets/aerc.go:568 +0xec git.sr.ht/~rjarry/aerc/widgets.(*Aerc).BeginExCommand.func2() git.sr.ht/~rjarry/aerc/widgets/aerc.go:590 +0x4c git.sr.ht/~rjarry/aerc/widgets.(*ExLine).Event(0xc009453860, {0xbb6820?, 0xc009baa320?}) git.sr.ht/~rjarry/aerc/widgets/exline.go:81 +0xbc git.sr.ht/~rjarry/aerc/widgets.(*Aerc).Event(0xc009ab1950?, {0xbb6820?, 0xc009baa320?}) git.sr.ht/~rjarry/aerc/widgets/aerc.go:285 +0x470 git.sr.ht/~rjarry/aerc/lib/ui.(*UI).ProcessEvents(0xc000327540) git.sr.ht/~rjarry/aerc/lib/ui/ui.go:117 +0x202 created by main.main git.sr.ht/~rjarry/aerc/aerc.go:244 +0x94c Protect Composer.editable and Composer.focus with a mutex. Reported-by: Bence Ferdinandy <bence@ferdinandy.com> Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
This commit is contained in:
parent
0e50f29bf3
commit
bf2bf8c242
1 changed files with 26 additions and 0 deletions
|
@ -8,6 +8,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/emersion/go-message/mail"
|
"github.com/emersion/go-message/mail"
|
||||||
|
@ -28,6 +29,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Composer struct {
|
type Composer struct {
|
||||||
|
sync.Mutex
|
||||||
editors map[string]*headerEditor // indexes in lower case (from / cc / bcc)
|
editors map[string]*headerEditor // indexes in lower case (from / cc / bcc)
|
||||||
header *mail.Header
|
header *mail.Header
|
||||||
parent models.OriginalMail // parent of current message, only set if reply
|
parent models.OriginalMail // parent of current message, only set if reply
|
||||||
|
@ -131,6 +133,8 @@ func (c *Composer) SwitchAccount(newAcct *AccountView) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) setupFor(acct *AccountView) error {
|
func (c *Composer) setupFor(acct *AccountView) error {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
// set new account and accountConfig
|
// set new account and accountConfig
|
||||||
c.acct = acct
|
c.acct = acct
|
||||||
c.acctConfig = acct.AccountConfig()
|
c.acctConfig = acct.AccountConfig()
|
||||||
|
@ -524,6 +528,8 @@ func (c *Composer) readSignatureFromFile() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) FocusTerminal() *Composer {
|
func (c *Composer) FocusTerminal() *Composer {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
if c.editor == nil {
|
if c.editor == nil {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
@ -587,6 +593,8 @@ func (c *Composer) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) Bindings() string {
|
func (c *Composer) Bindings() string {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
switch c.editor {
|
switch c.editor {
|
||||||
case nil:
|
case nil:
|
||||||
return "compose::review"
|
return "compose::review"
|
||||||
|
@ -598,6 +606,8 @@ func (c *Composer) Bindings() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) Event(event tcell.Event) bool {
|
func (c *Composer) Event(event tcell.Event) bool {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
if c.editor != nil {
|
if c.editor != nil {
|
||||||
return c.focusable[c.focused].Event(event)
|
return c.focusable[c.focused].Event(event)
|
||||||
}
|
}
|
||||||
|
@ -605,6 +615,8 @@ func (c *Composer) Event(event tcell.Event) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) MouseEvent(localX int, localY int, event tcell.Event) {
|
func (c *Composer) MouseEvent(localX int, localY int, event tcell.Event) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
c.grid.MouseEvent(localX, localY, event)
|
c.grid.MouseEvent(localX, localY, event)
|
||||||
for _, e := range c.focusable {
|
for _, e := range c.focusable {
|
||||||
he, ok := e.(*headerEditor)
|
he, ok := e.(*headerEditor)
|
||||||
|
@ -615,7 +627,9 @@ func (c *Composer) MouseEvent(localX int, localY int, event tcell.Event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) Focus(focus bool) {
|
func (c *Composer) Focus(focus bool) {
|
||||||
|
c.Lock()
|
||||||
c.focusable[c.focused].Focus(focus)
|
c.focusable[c.focused].Focus(focus)
|
||||||
|
c.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) Config() *config.AccountConfig {
|
func (c *Composer) Config() *config.AccountConfig {
|
||||||
|
@ -873,6 +887,8 @@ func (c *Composer) termEvent(event tcell.Event) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) termClosed(err error) {
|
func (c *Composer) termClosed(err error) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
if c.editor == nil {
|
if c.editor == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -888,6 +904,8 @@ func (c *Composer) termClosed(err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) ShowTerminal() {
|
func (c *Composer) ShowTerminal() {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
if c.editor != nil {
|
if c.editor != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -910,6 +928,8 @@ func (c *Composer) ShowTerminal() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) PrevField() {
|
func (c *Composer) PrevField() {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
c.focusable[c.focused].Focus(false)
|
c.focusable[c.focused].Focus(false)
|
||||||
c.focused--
|
c.focused--
|
||||||
if c.focused == -1 {
|
if c.focused == -1 {
|
||||||
|
@ -919,12 +939,16 @@ func (c *Composer) PrevField() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) NextField() {
|
func (c *Composer) NextField() {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
c.focusable[c.focused].Focus(false)
|
c.focusable[c.focused].Focus(false)
|
||||||
c.focused = (c.focused + 1) % len(c.focusable)
|
c.focused = (c.focused + 1) % len(c.focusable)
|
||||||
c.focusable[c.focused].Focus(true)
|
c.focusable[c.focused].Focus(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composer) FocusEditor(editor string) {
|
func (c *Composer) FocusEditor(editor string) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
editor = strings.ToLower(editor)
|
editor = strings.ToLower(editor)
|
||||||
c.focusable[c.focused].Focus(false)
|
c.focusable[c.focused].Focus(false)
|
||||||
for i, f := range c.focusable {
|
for i, f := range c.focusable {
|
||||||
|
@ -939,6 +963,8 @@ func (c *Composer) FocusEditor(editor string) {
|
||||||
|
|
||||||
// AddEditor appends a new header editor to the compose window.
|
// AddEditor appends a new header editor to the compose window.
|
||||||
func (c *Composer) AddEditor(header string, value string, appendHeader bool) {
|
func (c *Composer) AddEditor(header string, value string, appendHeader bool) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
var editor *headerEditor
|
var editor *headerEditor
|
||||||
header = strings.ToLower(header)
|
header = strings.ToLower(header)
|
||||||
if e, ok := c.editors[header]; ok {
|
if e, ok := c.editors[header]; ok {
|
||||||
|
|
Loading…
Reference in a new issue