Skip to content

Segfault when curses.screen.use() runs on a terminal-less screen #154786

Description

@serhiy-storchaka

Crash report

screen.use() makes its screen current for the callback, by calling use_screen(). A screen returned by new_prescr() has no terminal, so operations that need one crash inside curses.

import curses, os
fd = os.openpty()[1]
curses.newterm('xterm', fd, fd)
pre = curses.new_prescr()
pre.use(lambda s: curses.newwin(3, 3).refresh())    # Segmentation fault

This is the crash of gh-154749 through a different door: use() does not go through set_term(), so GH-154750 does not affect it.

Rejecting the screen here is not an option: use() is the only thing left to do with a new_prescr() screen -- its other members are close() and stdscr, which is None -- so pre.use(lambda s: curses.use_env(False)) has to keep working.

Eleven window methods crash in such a callback -- refresh(), noutrefresh(), getch(), getkey(), get_wch(), getstr(), get_wstr(), echochar(), keypad(), idlok(), idcok() -- and newwin() and newpad() return a window whose delwin() fails.

While a screen with no terminal is current, the C global stdscr is NULL, whichever way it became current. Checking that where a terminal is required covers use() and set_term() alike.

new_prescr() and screen.use() are new in 3.16 (gh-90092), and NetBSD curses has neither, so this is reachable only on ncurses in 3.16.

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions