[Python-Dev] Patch review [ 723201 ] PyArg_ParseTuple problem with 'L' format (original) (raw)
Michiel Jan Laurens de Hoon mdehoon at ims.u-tokyo.ac.jp
Thu Jan 20 14🔞52 CET 2005
- Previous message: [Python-Dev] python-dev Summary for 2004-12-01 through 2004-12-15 [draft]
- Next message: [Python-Dev] ANN: Free Trac/Subversion hosting at Python-Hosting.com (fwd)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Patch review [ 723201 ] PyArg_ParseTuple problem with 'L' format
The PyArg_ParseTuple function (PyObject *args, char *format, ...) parses the arguments args and stores them in the variables specified following the format argument. If format=="i", indicating an integer, but the corresponding Python object in args is not a Python int or long, a TypeError is thrown:
TypeError: an integer is required
For the "L" format, indicating a long long, instead a SystemError is thrown:
SystemError: Objects/longobject.c:788: bad argument to internal function
The submitted patch fixes this, however I think it is not the best way to do it. The original code (part of the convertsimple function in Python/getargs.c) is
case 'L': {/* PY_LONG_LONG */
PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * );
PY_LONG_LONG ival = PyLong_AsLongLong( arg );
if( ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) {
return converterr("long<L>", arg, msgbuf, bufsize);
} else {
*p = ival;
}
break;
}
In the patch, a PyLong_Check and a PyInt_Check are added:
case 'L': {/* PY_LONG_LONG */
PY_LONG_LONG *p = va_arg(*p_va, PY_LONG_LONG *);
PY_LONG_LONG ival;
/* ********** patch starts here ********** */
if (!PyLong_Check(arg) && !PyInt_Check(arg))
return converterr("long<L>", arg, msgbuf, bufsize);
/* ********** patch ends here ********** */
ival = PyLong_AsLongLong(arg);
if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred()) {
return converterr("long<L>", arg, msgbuf, bufsize);
} else {
*p = ival;
}
break;
}
However, the PyLong_AsLongLong function (in Objects/longobject.c) also contains a call to PyLong_Check and PyInt_Check, so there should be no need for another such check here:
PY_LONG_LONG PyLong_AsLongLong(PyObject *vv) { PY_LONG_LONG bytes; int one = 1; int res;
if (vv == NULL) {
PyErr_BadInternalCall();
return -1;
}
if (!PyLong_Check(vv)) {
if (PyInt_Check(vv))
return (PY_LONG_LONG)PyInt_AsLong(vv);
PyErr_BadInternalCall();
return -1;
}
A better solution would be to replace the PyErr_BadInternalCall() in the PyLong_AsLongLong function by PyErr_SetString(PyExc_TypeError, "an integer is required"); This would make it consistent with PyInt_AsLong in Objects/intobject.c:
long PyInt_AsLong(register PyObject *op) { PyNumberMethods *nb; PyIntObject *io; long val;
if (op && PyInt_Check(op))
return PyInt_AS_LONG((PyIntObject*) op);
if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
nb->nb_int == NULL) {
PyErr_SetString(PyExc_TypeError, "an integer is required");
return -1;
}
By the way, I noticed that a Python float is converted to an int (with a deprecation warning), while trying to convert a Python float into a long long int results in a TypeError. Also, I'm not sure about the function of the calls to converterr (in various places in the convertsimple function); none of the argument type errors seem to lead to the warning messages created by converterr.
--Michiel.
-- Michiel de Hoon, Assistant Professor University of Tokyo, Institute of Medical Science Human Genome Center 4-6-1 Shirokane-dai, Minato-ku Tokyo 108-8639 Japan http://bonsai.ims.u-tokyo.ac.jp/~mdehoon
- Previous message: [Python-Dev] python-dev Summary for 2004-12-01 through 2004-12-15 [draft]
- Next message: [Python-Dev] ANN: Free Trac/Subversion hosting at Python-Hosting.com (fwd)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]