From 5c0f1e725db9529bec5791b17d41ede54b04db4d Mon Sep 17 00:00:00 2001 From: Thomas O'Dowd Date: Mon, 27 Feb 2023 17:22:18 +0900 Subject: [PATCH] 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 ``` --- readline.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readline.go b/readline.go index 63b9171..03520cc 100644 --- a/readline.go +++ b/readline.go @@ -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