Search code examples
pythoncurses

Stack overflow in python's curses. Is it bug in the module?


I'm only beginner in using 'curses' and cannot say for sure whether it is a bug in the python's 'curses' module or my incorrect usage.

I have the following test code:

import curses
import curses.textpad

screen = curses.initscr()
curses.noecho()
cl = curses.newwin( 15, 80, 10, 1 )
txtbox = curses.textpad.Textbox(cl,insert_mode=True)

def main( scr ):
    global txtbox
    s = txtbox.edit()
    print(s)    

if __name__ == '__main__':
    ret = curses.wrapper( main )

When I run it, it starts OK, but when any key is pressed, it starts an infinite recursion and causes stack overflow. As can be seen in the curses/textpad.py code, the function which handles key events actually calls itself:

def _insert_printable_char(self, ch):
    (y, x) = self.win.getyx()
    if y < self.maxy or x < self.maxx:
        if self.insert_mode:
            oldch = self.win.inch()

        try:
            self.win.addch(ch)
        except curses.error:
            pass
        if self.insert_mode:
            (backy, backx) = self.win.getyx()
            if curses.ascii.isprint(oldch):
                self._insert_printable_char(oldch) # <--- Is it bug?
                self.win.move(backy, backx)

Is it bug in the python's textpad.py module, or maybe some curses' initialization steps are missed in my code?


Solution

  • I can reproduce the problem and it seems to be triggered by making the window underlying the textbox "too wide" in insert mode. Avoiding multiple initialization (the wrapper does it all), consider:

    import curses
    import curses.textpad
    import curses.wrapper
    
    def main(scr):
        win = curses.newwin( 15, 60, 10, 1 )
        txtbox = curses.textpad.Textbox(win, insert_mode=True)
        s = txtbox.edit()
        return s
    
    if __name__ == '__main__':
        ret = curses.wrapper( main )
        print ret
    

    But if you change the 2nd arg to newwin back to 80, the bug does trigger. (The recursion in _insert_printable_char to implement insert mode seems fine -- it's supposed to terminate because it eventually encounters the border or a non-printable character, but apparently it doesn't when the window is too broad).

    I'll keep debugging, adding logging to see exactly what's going wrong, but meanwhile I wanted to post this because it's possible that you can do with a slightly-narrower window and avoid triggering the bug).