Skip to content

curses cell text is silently truncated at an embedded NUL #155877

Closed

Description

@fedonman

Bug description:

curses.complexchar() keeps only the text before an embedded NUL, so complexchar('a\0\u0301') silently drops the combining acute, and complexchar('\0') builds a cell with no text at all, whose repr() is not a valid constructor call.

import curses

print(repr(curses.complexchar('a\0\u0301')))
print(repr(curses.complexchar('a\u0301')))
r = repr(curses.complexchar('\0'))
print(r)
eval(r, {'curses': curses})
curses.complexchar('a')
curses.complexchar('á')
curses.complexchar('')
Traceback (most recent call last):
  File "/tmp/bug.py", line 7, in <module>
    eval(r, {'curses': curses})
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
TypeError: expect a string of 1 to 5 characters, got a str of length 0

The empty cell is worse than the truncation: window.addstr(curses.complexstr([curses.complexchar('\0'), curses.complexchar('B')])) returns None having written nothing. The same text reaches the same converter through window.addch(), insch(), echochar(), hline(), vline(), bkgd(), bkgdset(), border() and box(), and curses.complexstr('a\0b') drops the NUL and returns two cells.

Expected: ValueError: embedded null character, which window.addstr('a\0b') already raises.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. serhiy-storchaka commented on Aug 16, 2026

    @serhiy-storchaka
    Member

    addch('\0') was always accepted (it is equivalent to addch(0)), so I think addch(complexchar('\0')) should work the same way.

    The repr for empty cell is complexchar('\0') in the narrow build, it should be the same in the wide build.

    Silent truncation after embedded NUL is not good, we try to detect such errors.

  2. added
    type-bugAn unexpected behavior, bug, or error
    on Aug 16, 2026
  3. serhiy-storchaka commented on Aug 21, 2026

    @serhiy-storchaka
    Member

    complexchar('\0') can be read back by in_wch(). This is why it should be supported. It is more complex for complexstr with embedded NUL. I have not found function which can return it: in_wstr() and instr() skip NUL, in_wchstr() truncates on NUL. And the output functions vary in their handling of NUL too. So it is safe to reject embedded NUL in complexstr. Other option -- allow embedded NUL in complexstr, but reject it at write time instead.

  4. added a commit that references this issue on Aug 21, 2026
  5. serhiy-storchaka commented on Aug 21, 2026

    @serhiy-storchaka
    Member

    Thank you for your reports and fixes @fedonman.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions