From 6dbff33be848ed875f3769be6b866438b099aa3a Mon Sep 17 00:00:00 2001 From: Thomas Wouters Date: Tue, 25 Apr 2006 13:53:23 +0000 Subject: [PATCH] SF bug/patch #1433877: string parameter to ioctl not null terminated The new char-array used in ioctl calls wasn't explicitly NUL-terminated; quite probably the cause for the test_pty failures on Solaris that we circumvented earlier. (I wasn't able to reproduce it with this patch, but it has been somewhat elusive to start with.) --- Lib/test/test_pty.py | 9 +-------- Misc/ACKS | 1 + Modules/fcntlmodule.c | 15 ++++++++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py index 99e01b67bb0..7b1f460ff11 100644 --- a/Lib/test/test_pty.py +++ b/Lib/test/test_pty.py @@ -4,13 +4,6 @@ from test.test_support import verbose, TestFailed, TestSkipped TEST_STRING_1 = "I wish to buy a fish license.\n" TEST_STRING_2 = "For my pet fish, Eric.\n" -# Solaris (at least 2.9 and 2.10) seem to have a fickle isatty(). The first -# test below, testing the result of os.openpty() for tty-ness, sometimes -# (but not always) fails. The second isatty test, in the sub-process, always -# works. Allow that fickle first test to fail on these platforms, since it -# doesn't actually affect functionality. -fickle_isatty = ["sunos5"] - if verbose: def debug(msg): print msg @@ -54,7 +47,7 @@ def test_basic_pty(): # " An optional feature could not be imported " ... ? raise TestSkipped, "Pseudo-terminals (seemingly) not functional." - if not os.isatty(slave_fd) and sys.platform not in fickle_isatty: + if not os.isatty(slave_fd): raise TestFailed, "slave_fd is not a tty" debug("Writing to slave_fd") diff --git a/Misc/ACKS b/Misc/ACKS index de1d8a2b25b..3f1b47c4f38 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -33,6 +33,7 @@ Greg Ball Luigi Ballabio Michael J. Barber Chris Barker +Quentin Barnes Cesar Eduardo Barros Des Barry Ulf Bartelt diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index a368494c969..477af06289a 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -95,6 +95,7 @@ corresponding to the return value of the fcntl call in the C code."); static PyObject * fcntl_ioctl(PyObject *self, PyObject *args) { +#define IOCTL_BUFSZ 1024 int fd; /* In PyArg_ParseTuple below, use the unsigned int 'I' format for the signed int 'code' variable, because Python turns 0x8000000 @@ -106,7 +107,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) char *str; Py_ssize_t len; int mutate_arg = 1; - char buf[1024]; + char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */ if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl", conv_descriptor, &fd, &code, @@ -114,8 +115,9 @@ fcntl_ioctl(PyObject *self, PyObject *args) char *arg; if (mutate_arg) { - if (len <= sizeof buf) { + if (len <= IOCTL_BUFSZ) { memcpy(buf, str, len); + buf[len] = '\0'; arg = buf; } else { @@ -123,13 +125,14 @@ fcntl_ioctl(PyObject *self, PyObject *args) } } else { - if (len > sizeof buf) { + if (len > IOCTL_BUFSZ) { PyErr_SetString(PyExc_ValueError, "ioctl string arg too long"); return NULL; } else { memcpy(buf, str, len); + buf[len] = '\0'; arg = buf; } } @@ -141,7 +144,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) else { ret = ioctl(fd, code, arg); } - if (mutate_arg && (len < sizeof buf)) { + if (mutate_arg && (len < IOCTL_BUFSZ)) { memcpy(str, buf, len); } if (ret < 0) { @@ -159,12 +162,13 @@ fcntl_ioctl(PyObject *self, PyObject *args) PyErr_Clear(); if (PyArg_ParseTuple(args, "O&Is#:ioctl", conv_descriptor, &fd, &code, &str, &len)) { - if (len > sizeof buf) { + if (len > IOCTL_BUFSZ) { PyErr_SetString(PyExc_ValueError, "ioctl string arg too long"); return NULL; } memcpy(buf, str, len); + buf[len] = '\0'; Py_BEGIN_ALLOW_THREADS ret = ioctl(fd, code, buf); Py_END_ALLOW_THREADS @@ -195,6 +199,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) return NULL; } return PyInt_FromLong((long)ret); +#undef IOCTL_BUFSZ } PyDoc_STRVAR(ioctl_doc,