Skip to content

Commit 3f8cebf

Browse files
committed
gh-155877: Reject a NUL cell in curses.complexstr() from an iterable
GH-156158 rejected a NUL in complexstr() given a str, but the iterable path packed each item without that check, so the example from the issue still built and addstr() dropped every cell after the NUL.
1 parent e5ef47e commit 3f8cebf

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

‎Lib/test/test_curses.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,8 @@ def test_cell_null_char(self):
11381138
# A string of cells cannot hold a NUL: it would end a batch write.
11391139
self.assertRaises(ValueError, curses.complexstr, 'a\0b')
11401140
self.assertRaises(ValueError, curses.complexstr, '\0')
1141+
self.assertRaises(ValueError, curses.complexstr, ['a', '\0', 'b'])
1142+
self.assertRaises(ValueError, curses.complexstr, [cell, 'b'])
11411143

11421144
def test_add_string_behavior(self):
11431145
# addstr() advances the cursor past the written text; addnstr()

‎Modules/_cursesmodule.c‎

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,15 +1300,35 @@ curses_pack_cell(cursesmodule_state *state, PyObject *item, curses_cell_t *out)
13001300
{
13011301
if (Py_IS_TYPE(item, state->complexchar_type)) {
13021302
*out = _PyCursesComplexCharObject_CAST(item)->cval;
1303-
return 0;
13041303
}
1305-
if (PyUnicode_Check(item)) {
1306-
return curses_cell_pack(state, out, item, A_NORMAL, 0, "complexstr");
1304+
else if (PyUnicode_Check(item)) {
1305+
if (curses_cell_pack(state, out, item, A_NORMAL, 0, "complexstr") < 0) {
1306+
return -1;
1307+
}
13071308
}
1308-
PyErr_Format(PyExc_TypeError,
1309-
"complexstr cell must be a complexchar or a str, not %T",
1310-
item);
1311-
return -1;
1309+
else {
1310+
PyErr_Format(PyExc_TypeError,
1311+
"complexstr cell must be a complexchar or a str, not %T",
1312+
item);
1313+
return -1;
1314+
}
1315+
#ifdef HAVE_NCURSESW
1316+
wchar_t wstr[CCHARW_MAX + 1];
1317+
attr_t attr;
1318+
int pair;
1319+
if (curses_getcchar(out, wstr, &attr, &pair) == ERR) {
1320+
PyErr_SetString(state->error, "getcchar() returned ERR");
1321+
return -1;
1322+
}
1323+
int nul = wstr[0] == L'\0';
1324+
#else
1325+
int nul = (*out & A_CHARTEXT) == 0;
1326+
#endif
1327+
if (nul) {
1328+
PyErr_SetString(PyExc_ValueError, "embedded null character");
1329+
return -1;
1330+
}
1331+
return 0;
13121332
}
13131333

13141334
/* Wrap a buffer of len cells in a new complexstr, copying them in. tp_alloc

0 commit comments

Comments
 (0)