[ 555817 ] Flawed fcntl.ioctl implementation.

with my patch that allows for an array to be mutated when passed
as the buffer argument to ioctl() (details complicated by
backwards compatibility considerations -- read the docs!).
This commit is contained in:
Michael W. Hudson 2003-03-03 12:29:42 +00:00
parent 122152451e
commit f008998668
4 changed files with 171 additions and 18 deletions

View file

@ -99,8 +99,62 @@ fcntl_ioctl(PyObject *self, PyObject *args)
int ret;
char *str;
int len;
int mutate_arg = 0;
char buf[1024];
if (PyArg_ParseTuple(args, "O&iw#|i:ioctl",
conv_descriptor, &fd, &code,
&str, &len, &mutate_arg)) {
char *arg;
if (PyTuple_Size(args) == 3) {
/* warning goes here in 2.4 */
mutate_arg = 0;
}
if (mutate_arg) {
if (len <= sizeof buf) {
memcpy(buf, str, len);
arg = buf;
}
else {
arg = str;
}
}
else {
if (len > sizeof buf) {
PyErr_SetString(PyExc_ValueError,
"ioctl string arg too long");
return NULL;
}
else {
memcpy(buf, str, len);
arg = buf;
}
}
if (buf == arg) {
Py_BEGIN_ALLOW_THREADS /* think array.resize() */
ret = ioctl(fd, code, arg);
Py_END_ALLOW_THREADS
}
else {
ret = ioctl(fd, code, arg);
}
if (mutate_arg && (len < sizeof buf)) {
memcpy(str, buf, len);
}
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
if (mutate_arg) {
return PyInt_FromLong(ret);
}
else {
return PyString_FromStringAndSize(buf, len);
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O&is#:ioctl",
conv_descriptor, &fd, &code, &str, &len)) {
if (len > sizeof buf) {
@ -123,7 +177,7 @@ fcntl_ioctl(PyObject *self, PyObject *args)
arg = 0;
if (!PyArg_ParseTuple(args,
"O&i|i;ioctl requires a file or file descriptor,"
" an integer and optionally a third integer or a string",
" an integer and optionally a integer or buffer argument",
conv_descriptor, &fd, &code, &arg)) {
return NULL;
}
@ -138,17 +192,35 @@ fcntl_ioctl(PyObject *self, PyObject *args)
}
PyDoc_STRVAR(ioctl_doc,
"ioctl(fd, opt, [arg])\n\
"ioctl(fd, opt[, arg[, mutate_flag]])\n\
\n\
Perform the requested operation on file descriptor fd. The operation\n\
is defined by op and is operating system dependent. Typically these\n\
codes can be retrieved from the library module IOCTL. The argument arg\n\
is optional, and defaults to 0; it may be an int or a string. If arg is\n\
given as a string, the return value of ioctl is a string of that length,\n\
containing the resulting value put in the arg buffer by the operating system.\n\
The length of the arg string is not allowed to exceed 1024 bytes. If the arg\n\
given is an integer or if none is specified, the result value is an integer\n\
corresponding to the return value of the ioctl call in the C code.");
Perform the requested operation on file descriptor fd. The operation is\n\
defined by op and is operating system dependent. Typically these codes are\n\
retrieved from the fcntl or termios library modules.\n\
\n\
The argument arg is optional, and defaults to 0; it may be an int or a\n\
buffer containing character data (most likely a string or an array). \n\
\n\
If the argument is a mutable buffer (such as an array) and if the\n\
mutate_flag argument (which is only allowed in this case) is true then the\n\
buffer is (in effect) passed to the operating system and changes made by\n\
the OS will be reflected in the contents of the buffer after the call has\n\
returned. The return value is the integer returned by the ioctl system\n\
call.\n\
\n\
If the argument is a mutable buffer and the mutable_flag argument is not\n\
passed or is false, the behavior is as if a string had been passed. This\n\
behavior will change in future releases of Python.\n\
\n\
If the argument is an immutable buffer (most likely a string) then a copy\n\
of the buffer is passed to the operating system and the return value is a\n\
string of the same length containing whatever the operating system put in\n\
the buffer. The length of the arg buffer in this case is not allowed to\n\
exceed 1024 bytes.\n\
\n\
If the arg given is an integer or if none is specified, the result value is\n\
an integer corresponding to the return value of the ioctl call in the C\n\
code.");
/* flock(fd, operation) */