fix curses.newwin() crash on narrow terminals in TUI dialogs
show_confirm() sized its window purely from message content, with no upper bound — a long line (the Cryptgeon password URL in the post-issuance "send email?" prompt) could easily exceed a narrow terminal's width (e.g. a serial console), making curses.newwin() raise "curses function returned NULL" and crash the whole app. show_cert_form() had the same unguarded newwin() call, just with a fixed 13x62 size instead of content-driven. Clamp both windows' height/width to the actual screen size, and wrap newwin() itself in try/except as a last-resort fallback (declined confirm / cancelled form) in case clamping still isn't enough. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -651,9 +651,15 @@ def show_confirm(stdscr, message: str) -> bool:
|
||||
"""Y/N modal dialog. Returns True if user presses y/Y."""
|
||||
sh, sw = stdscr.getmaxyx()
|
||||
lines = message.splitlines()
|
||||
h = len(lines) + 6
|
||||
w = max(max(len(l) for l in lines) + 6, 38)
|
||||
win = curses.newwin(h, w, (sh - h) // 2, (sw - w) // 2)
|
||||
# Clamp to the screen: an unbounded width (e.g. a long Cryptgeon URL line)
|
||||
# makes curses.newwin() raise "curses function returned NULL" outright on
|
||||
# a narrow terminal (e.g. a serial console) instead of just wrapping badly.
|
||||
h = min(len(lines) + 6, sh)
|
||||
w = min(max(max(len(l) for l in lines) + 6, 38), sw)
|
||||
try:
|
||||
win = curses.newwin(h, w, max(0, (sh - h) // 2), max(0, (sw - w) // 2))
|
||||
except curses.error:
|
||||
return False
|
||||
win.keypad(True)
|
||||
draw_box(win, "Confirm")
|
||||
for i, line in enumerate(lines):
|
||||
@@ -704,8 +710,14 @@ def show_cert_form(
|
||||
Tab / Shift-Tab / Up / Down cycle fields and buttons. F5 regenerates password.
|
||||
Enter or Space activates the focused button. Ctrl-G confirms immediately. Escape cancels."""
|
||||
sh, sw = stdscr.getmaxyx()
|
||||
h, w = 13, 62
|
||||
win = curses.newwin(h, w, (sh - h) // 2, (sw - w) // 2)
|
||||
# Clamp to the screen so curses.newwin() can't raise "curses function
|
||||
# returned NULL" outright on a terminal narrower/shorter than the usual
|
||||
# 80x24 (e.g. a serial console with an unusually small viewport).
|
||||
h, w = min(13, sh), min(62, sw)
|
||||
try:
|
||||
win = curses.newwin(h, w, max(0, (sh - h) // 2), max(0, (sw - w) // 2))
|
||||
except curses.error:
|
||||
return CertFormResult(cn=cn, email="", password="", confirmed=False)
|
||||
win.keypad(True)
|
||||
fw = w - 6 # field width
|
||||
|
||||
|
||||
Reference in New Issue
Block a user