Skip to content

Commit a728080

Browse files
gh-156348: Fix the value of curses.ERR (GH-156349)
Setting the module constants with an unsigned conversion, needed for the chtype constants that can set bits beyond a 32-bit long, turned ERR from -1 into 18446744073709551615. Set ERR and OK with a signed conversion.
1 parent fe8ace3 commit a728080

2 files changed

Lines changed: 27 additions & 7 deletions

File tree

Lib/test/test_curses.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2984,6 +2984,11 @@ def test_has_extended_color_support(self):
29842984
r = curses.has_extended_color_support()
29852985
self.assertIsInstance(r, bool)
29862986

2987+
def test_err_and_ok(self):
2988+
# ERR is negative; it is not a chtype constant.
2989+
self.assertEqual(curses.ERR, -1)
2990+
self.assertEqual(curses.OK, 0)
2991+
29872992
def test_type_names(self):
29882993
# The curses types report their public module rather than the
29892994
# underscore extension that implements them.

Modules/_cursesmodule.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6657,11 +6657,10 @@ curses_init_dict(PyObject *module)
66576657
}
66586658
/* This was moved from initcurses() because it core dumped on SGI,
66596659
where they're not defined until you've called initscr() */
6660-
/* Use long long, not long: a chtype constant (the A_* attributes, ACS_*
6661-
and key codes) can set bits beyond a 32-bit long, which is what long is
6662-
on LLP64 platforms such as Windows -- A_DIM (0x80000000) would otherwise
6663-
be sign-extended to a negative number. long long is at least 64 bits
6664-
everywhere and still represents the negative ERR (-1). */
6660+
/* Use unsigned long long, not long: a chtype constant (the A_* attributes,
6661+
ACS_* and key codes) can set bits beyond a 32-bit long, which is what
6662+
long is on LLP64 platforms such as Windows -- A_DIM (0x80000000) would
6663+
otherwise be sign-extended to a negative number. */
66656664
#define SetDictInt(NAME, VALUE) \
66666665
do { \
66676666
PyObject *value = PyLong_FromUnsignedLongLong((unsigned long long)(VALUE)); \
@@ -9419,8 +9418,24 @@ cursesmodule_exec(PyObject *module)
94199418
} \
94209419
} while (0)
94219420

9422-
SetDictInt("ERR", ERR);
9423-
SetDictInt("OK", OK);
9421+
/* ERR is -1, so it needs a signed conversion, unlike the chtype
9422+
constants below. */
9423+
#define SetDictSignedInt(NAME, VALUE) \
9424+
do { \
9425+
PyObject *value = PyLong_FromLongLong((long long)(VALUE)); \
9426+
if (value == NULL) { \
9427+
return -1; \
9428+
} \
9429+
int rc = PyDict_SetItemString(module_dict, (NAME), value); \
9430+
Py_DECREF(value); \
9431+
if (rc < 0) { \
9432+
return -1; \
9433+
} \
9434+
} while (0)
9435+
9436+
SetDictSignedInt("ERR", ERR);
9437+
SetDictSignedInt("OK", OK);
9438+
#undef SetDictSignedInt
94249439

94259440
/* Here are some attributes you can add to chars to print */
94269441

0 commit comments

Comments
 (0)