Fix crash when cfg.Painter is nil after another SetConfig() call

The following example code calls SetConfig() one more time after
setting initializing readline instance with a different config.
This is a contrived example, but this is useful when an
application has a mode change and needs a different config
(not just the prompt as in this example).

```
package main

import (
	"fmt"
	"strings"
	"github.com/chzyer/readline"
)

func main() {
	l, err := readline.NewEx(&readline.Config{})
	if err != nil {
		panic(err)
	}
	defer l.Close()

	l.SetConfig(&readline.Config{Prompt: "> "})
	line, err := l.Readline()
	fmt.Printf("you: %s\n", strings.TrimSpace(line))
}
```

Without the fix, this program will crash like this:
```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x4c23b4]

goroutine 1 [running]:
github.com/chzyer/readline.(*RuneBuffer).output(0xc0000b21e0, 0x51f648, 0xc0000b6050, 0x0)
	/home/tpodowd/work/readline/runebuf.go:494 +0xd4
github.com/chzyer/readline.(*RuneBuffer).print(0xc0000b21e0)
	/home/tpodowd/work/readline/runebuf.go:475 +0x2b
github.com/chzyer/readline.(*RuneBuffer).Refresh(0xc0000b21e0, 0x0)
	/home/tpodowd/work/readline/runebuf.go:465 +0xbf
github.com/chzyer/readline.(*Operation).Runes(0xc0000bc000, 0x0, 0x0, 0x0, 0x0, 0x0)
	/home/tpodowd/work/readline/operation.go:390 +0xf2
github.com/chzyer/readline.(*Operation).String(...)
	/home/tpodowd/work/readline/operation.go:377
github.com/chzyer/readline.(*Instance).Readline(0xc0000a0060, 0xc0000b4120, 0xc0000b4000, 0x0, 0x4649c5)
	/home/tpodowd/work/readline/readline.go:257 +0x2f
main.main()
	/home/tpodowd/work/readline/example/paint/paint.go:17 +0xdd
exit status 2
```
This commit is contained in:
Thomas O'Dowd 2023-02-27 17:22:18 +09:00
parent 7f93d88cd5
commit 5c0f1e725d
1 changed files with 3 additions and 0 deletions

View File

@ -318,6 +318,9 @@ func (i *Instance) SetConfig(cfg *Config) *Config {
}
old := i.Config
i.Config = cfg
if cfg.Painter == nil {
cfg.Painter = &defaultPainter{}
}
i.Operation.SetConfig(cfg)
i.Terminal.SetConfig(cfg)
return old