This is an automated email from the ASF dual-hosted git repository. sjanc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git
commit 07d10d463aa3413f9545f858a10af44b9ae05377 Author: Szymon Janc <[email protected]> AuthorDate: Mon Oct 19 17:46:37 2026 +0200 newt/install: Fix panic on long answer to upgrade prompt The "Proceed? [Y/n]" prompt read the answer with bufio ReadLine. For a line longer than the reader buffer ReadLine returns more=true with a nil error, which was then passed to util.ChildNewtError(nil) and caused a nil pointer dereference. Read whole lines with ReadString instead, using a single reader for all attempts, so a long answer is treated as an invalid response. An answer terminated by EOF without newline is still accepted. Assisted-by: Claude:claude-opus-5-5 --- newt/install/install.go | 13 +++++++-- newt/install/install_test.go | 68 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/newt/install/install.go b/newt/install/install.go index 36faf4fd..2d48eea5 100644 --- a/newt/install/install.go +++ b/newt/install/install.go @@ -66,6 +66,7 @@ package install import ( "bufio" "fmt" + "io" "os" "strings" @@ -376,14 +377,20 @@ func (inst *Installer) installPrompt(vm deprepo.VersionMap, op installOp, } } + return askProceed(bufio.NewReader(os.Stdin)) +} + +// Asks the user whether to proceed and reads the answer from the specified +// reader. Returns true if the user wants to proceed. +func askProceed(rd *bufio.Reader) (bool, error) { for { fmt.Printf("Proceed? [Y/n] ") - line, more, err := bufio.NewReader(os.Stdin).ReadLine() - if more || err != nil { + line, err := rd.ReadString('\n') + if err != nil && (err != io.EOF || len(line) == 0) { return false, util.ChildNewtError(err) } - trimmed := strings.ToLower(strings.TrimSpace(string(line))) + trimmed := strings.ToLower(strings.TrimSpace(line)) if len(trimmed) == 0 || strings.HasPrefix(trimmed, "y") { // User wants to proceed. return true, nil diff --git a/newt/install/install_test.go b/newt/install/install_test.go new file mode 100644 index 00000000..2d776cd4 --- /dev/null +++ b/newt/install/install_test.go @@ -0,0 +1,68 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package install + +import ( + "bufio" + "strings" + "testing" +) + +func TestAskProceed(t *testing.T) { + long := strings.Repeat("x", 10000) + + tests := []struct { + name string + input string + proceed bool + err bool + }{ + {"empty", "\n", true, false}, + {"yes", "y\n", true, false}, + {"no", "n\n", false, false}, + {"yes without newline", "Y", true, false}, + {"eof", "", false, true}, + {"invalid then no", "foo\nn\n", false, false}, + {"long line then yes", long + "\ny\n", true, false}, + {"long line then no", long + "\nno\n", false, false}, + {"long yes line", "y" + long + "\n", true, false}, + {"long line then eof", long, false, true}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + rd := bufio.NewReader(strings.NewReader(tc.input)) + proceed, err := askProceed(rd) + if tc.err { + if err == nil { + t.Fatalf("expected error") + } + return + } + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if proceed != tc.proceed { + t.Fatalf("expected proceed=%v, got %v", + tc.proceed, proceed) + } + }) + } +}
