Kaydet (Commit) 6dbff33b authored tarafından Thomas Wouters's avatar Thomas Wouters

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.)
üst d798a181
...@@ -4,13 +4,6 @@ from test.test_support import verbose, TestFailed, TestSkipped ...@@ -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_1 = "I wish to buy a fish license.\n"
TEST_STRING_2 = "For my pet fish, Eric.\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: if verbose:
def debug(msg): def debug(msg):
print msg print msg
...@@ -54,7 +47,7 @@ def test_basic_pty(): ...@@ -54,7 +47,7 @@ def test_basic_pty():
# " An optional feature could not be imported " ... ? # " An optional feature could not be imported " ... ?
raise TestSkipped, "Pseudo-terminals (seemingly) not functional." 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" raise TestFailed, "slave_fd is not a tty"
debug("Writing to slave_fd") debug("Writing to slave_fd")
......
...@@ -33,6 +33,7 @@ Greg Ball ...@@ -33,6 +33,7 @@ Greg Ball
Luigi Ballabio Luigi Ballabio
Michael J. Barber Michael J. Barber
Chris Barker Chris Barker
Quentin Barnes
Cesar Eduardo Barros Cesar Eduardo Barros
Des Barry Des Barry
Ulf Bartelt Ulf Bartelt
......
...@@ -95,6 +95,7 @@ corresponding to the return value of the fcntl call in the C code."); ...@@ -95,6 +95,7 @@ corresponding to the return value of the fcntl call in the C code.");
static PyObject * static PyObject *
fcntl_ioctl(PyObject *self, PyObject *args) fcntl_ioctl(PyObject *self, PyObject *args)
{ {
#define IOCTL_BUFSZ 1024
int fd; int fd;
/* In PyArg_ParseTuple below, use the unsigned int 'I' format for /* In PyArg_ParseTuple below, use the unsigned int 'I' format for
the signed int 'code' variable, because Python turns 0x8000000 the signed int 'code' variable, because Python turns 0x8000000
...@@ -106,7 +107,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) ...@@ -106,7 +107,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
char *str; char *str;
Py_ssize_t len; Py_ssize_t len;
int mutate_arg = 1; int mutate_arg = 1;
char buf[1024]; char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */
if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl", if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",
conv_descriptor, &fd, &code, conv_descriptor, &fd, &code,
...@@ -114,8 +115,9 @@ fcntl_ioctl(PyObject *self, PyObject *args) ...@@ -114,8 +115,9 @@ fcntl_ioctl(PyObject *self, PyObject *args)
char *arg; char *arg;
if (mutate_arg) { if (mutate_arg) {
if (len <= sizeof buf) { if (len <= IOCTL_BUFSZ) {
memcpy(buf, str, len); memcpy(buf, str, len);
buf[len] = '\0';
arg = buf; arg = buf;
} }
else { else {
...@@ -123,13 +125,14 @@ fcntl_ioctl(PyObject *self, PyObject *args) ...@@ -123,13 +125,14 @@ fcntl_ioctl(PyObject *self, PyObject *args)
} }
} }
else { else {
if (len > sizeof buf) { if (len > IOCTL_BUFSZ) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"ioctl string arg too long"); "ioctl string arg too long");
return NULL; return NULL;
} }
else { else {
memcpy(buf, str, len); memcpy(buf, str, len);
buf[len] = '\0';
arg = buf; arg = buf;
} }
} }
...@@ -141,7 +144,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) ...@@ -141,7 +144,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
else { else {
ret = ioctl(fd, code, arg); ret = ioctl(fd, code, arg);
} }
if (mutate_arg && (len < sizeof buf)) { if (mutate_arg && (len < IOCTL_BUFSZ)) {
memcpy(str, buf, len); memcpy(str, buf, len);
} }
if (ret < 0) { if (ret < 0) {
...@@ -159,12 +162,13 @@ fcntl_ioctl(PyObject *self, PyObject *args) ...@@ -159,12 +162,13 @@ fcntl_ioctl(PyObject *self, PyObject *args)
PyErr_Clear(); PyErr_Clear();
if (PyArg_ParseTuple(args, "O&Is#:ioctl", if (PyArg_ParseTuple(args, "O&Is#:ioctl",
conv_descriptor, &fd, &code, &str, &len)) { conv_descriptor, &fd, &code, &str, &len)) {
if (len > sizeof buf) { if (len > IOCTL_BUFSZ) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"ioctl string arg too long"); "ioctl string arg too long");
return NULL; return NULL;
} }
memcpy(buf, str, len); memcpy(buf, str, len);
buf[len] = '\0';
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
ret = ioctl(fd, code, buf); ret = ioctl(fd, code, buf);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
...@@ -195,6 +199,7 @@ fcntl_ioctl(PyObject *self, PyObject *args) ...@@ -195,6 +199,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
return PyInt_FromLong((long)ret); return PyInt_FromLong((long)ret);
#undef IOCTL_BUFSZ
} }
PyDoc_STRVAR(ioctl_doc, PyDoc_STRVAR(ioctl_doc,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment