gh-119770: Make termios ioctl() constants positive (#119840)

This commit is contained in:
Victor Stinner 2024-05-31 17:18:40 +02:00 committed by GitHub
parent bcc1be39cb
commit 64ff1e217d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 32 additions and 18 deletions

View File

@ -66,23 +66,15 @@ class IoctlTests(unittest.TestCase):
# Test with a larger buffer, just for the record. # Test with a larger buffer, just for the record.
self._check_ioctl_mutate_len(2048) self._check_ioctl_mutate_len(2048)
def test_ioctl_signed_unsigned_code_param(self): @unittest.skipIf(pty is None, 'pty module required')
if not pty: def test_ioctl_set_window_size(self):
raise unittest.SkipTest('pty module required')
mfd, sfd = pty.openpty() mfd, sfd = pty.openpty()
try: try:
if termios.TIOCSWINSZ < 0: # (rows, columns, xpixel, ypixel)
set_winsz_opcode_maybe_neg = termios.TIOCSWINSZ our_winsz = struct.pack("HHHH", 20, 40, 0, 0)
set_winsz_opcode_pos = termios.TIOCSWINSZ & 0xffffffff result = fcntl.ioctl(mfd, termios.TIOCSWINSZ, our_winsz)
else: new_winsz = struct.unpack("HHHH", result)
set_winsz_opcode_pos = termios.TIOCSWINSZ self.assertEqual(new_winsz[:2], (20, 40))
set_winsz_opcode_maybe_neg, = struct.unpack("i",
struct.pack("I", termios.TIOCSWINSZ))
our_winsz = struct.pack("HHHH",80,25,0,0)
# test both with a positive and potentially negative ioctl code
new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_pos, our_winsz)
new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, our_winsz)
finally: finally:
os.close(mfd) os.close(mfd)
os.close(sfd) os.close(sfd)

View File

@ -211,6 +211,15 @@ class TestModule(unittest.TestCase):
self.assertLess(termios.VTIME, termios.NCCS) self.assertLess(termios.VTIME, termios.NCCS)
self.assertLess(termios.VMIN, termios.NCCS) self.assertLess(termios.VMIN, termios.NCCS)
def test_ioctl_constants(self):
# gh-119770: ioctl() constants must be positive
for name in dir(termios):
if not name.startswith('TIO'):
continue
value = getattr(termios, name)
with self.subTest(name=name):
self.assertGreaterEqual(value, 0)
def test_exception(self): def test_exception(self):
self.assertTrue(issubclass(termios.error, Exception)) self.assertTrue(issubclass(termios.error, Exception))
self.assertFalse(issubclass(termios.error, OSError)) self.assertFalse(issubclass(termios.error, OSError))

View File

@ -0,0 +1 @@
Make :mod:`termios` ``ioctl()`` constants positive. Patch by Victor Stinner.

View File

@ -1352,9 +1352,21 @@ termios_exec(PyObject *mod)
} }
while (constant->name != NULL) { while (constant->name != NULL) {
if (PyModule_AddIntConstant( if (strncmp(constant->name, "TIO", 3) == 0) {
mod, constant->name, constant->value) < 0) { // gh-119770: Convert value to unsigned int for ioctl() constants,
return -1; // constants can be negative on macOS whereas ioctl() expects an
// unsigned long 'request'.
unsigned int value = constant->value & UINT_MAX;
if (PyModule_Add(mod, constant->name,
PyLong_FromUnsignedLong(value)) < 0) {
return -1;
}
}
else {
if (PyModule_AddIntConstant(
mod, constant->name, constant->value) < 0) {
return -1;
}
} }
++constant; ++constant;
} }