summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_ioctl.py31
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/fcntlmodule.c2
3 files changed, 31 insertions, 6 deletions
diff --git a/Lib/test/test_ioctl.py b/Lib/test/test_ioctl.py
index 07dac09..6c7ab0c 100644
--- a/Lib/test/test_ioctl.py
+++ b/Lib/test/test_ioctl.py
@@ -1,3 +1,4 @@
+import array
import unittest
from test.support import run_unittest, import_module, get_attribute
import os, struct
@@ -34,16 +35,36 @@ class IoctlTests(unittest.TestCase):
rpgrp = struct.unpack("i", r)[0]
self.assertIn(rpgrp, ids)
- def test_ioctl_mutate(self):
- import array
- buf = array.array('i', [0])
+ def _check_ioctl_mutate_len(self, nbytes=None):
+ buf = array.array('i')
+ intsize = buf.itemsize
ids = (os.getpgrp(), os.getsid(0))
- tty = open("/dev/tty", "r")
- r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, 1)
+ # A fill value unlikely to be in `ids`
+ fill = -12345
+ if nbytes is not None:
+ # Extend the buffer so that it is exactly `nbytes` bytes long
+ buf.extend([fill] * (nbytes // intsize))
+ self.assertEqual(len(buf) * intsize, nbytes) # sanity check
+ else:
+ buf.append(fill)
+ with open("/dev/tty", "r") as tty:
+ r = fcntl.ioctl(tty, termios.TIOCGPGRP, buf, 1)
rpgrp = buf[0]
self.assertEquals(r, 0)
self.assertIn(rpgrp, ids)
+ def test_ioctl_mutate(self):
+ self._check_ioctl_mutate_len()
+
+ def test_ioctl_mutate_1024(self):
+ # Issue #9758: a mutable buffer of exactly 1024 bytes wouldn't be
+ # copied back after the system call.
+ self._check_ioctl_mutate_len(1024)
+
+ def test_ioctl_mutate_2048(self):
+ # Test with a larger buffer, just for the record.
+ self._check_ioctl_mutate_len(2048)
+
def test_ioctl_signed_unsigned_code_param(self):
if not pty:
raise unittest.SkipTest('pty module required')
diff --git a/Misc/NEWS b/Misc/NEWS
index 06a3f53..81df803 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@ Core and Builtins
Library
-------
+- Issue #9758: When fcntl.ioctl() was called with mutable_flag set to True,
+ and the passed buffer was exactly 1024 bytes long, the buffer wouldn't
+ be updated back after the system call. Original patch by Brian Brazil.
+
- Updates to the random module:
* Document which parts of the module are guaranteed to stay the same
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index a7cdccb..bfc5985 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -157,7 +157,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
else {
ret = ioctl(fd, code, arg);
}
- if (mutate_arg && (len < IOCTL_BUFSZ)) {
+ if (mutate_arg && (len <= IOCTL_BUFSZ)) {
memcpy(str, buf, len);
}
PyBuffer_Release(&pstr); /* No further access to str below this point */