Skip to content

Commit 3abca12

Browse files
committed
SF bug #475327: type() produces incorrect error msg
object.h: Added PyType_CheckExact macro. typeobject.c, type_new(): + Use the new macro. + Assert that the arguments have the right types rather than do incomplete runtime checks "sometimes". + If this isn't the 1-argument flavor() of type, and there aren't 3 args total, produce a "types() takes 1 or 3 args" msg before PyArg_ParseTupleAndKeywords produces a "takes exactly 3" msg.
1 parent 4d85953 commit 3abca12

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

Include/object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ extern DL_IMPORT(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */
312312
extern DL_IMPORT(PyTypeObject) PySuper_Type; /* built-in 'super' */
313313

314314
#define PyType_Check(op) PyObject_TypeCheck(op, &PyType_Type)
315+
#define PyType_CheckExact(op) ((op)->ob_type == &PyType_Type)
315316

316317
extern DL_IMPORT(int) PyType_Ready(PyTypeObject *);
317318
extern DL_IMPORT(PyObject *) PyType_GenericAlloc(PyTypeObject *, int);

Objects/typeobject.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -713,13 +713,28 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
713713
PyMemberDef *mp;
714714
int i, nbases, nslots, slotoffset, add_dict, add_weak;
715715

716+
assert(args != NULL && PyTuple_Check(args));
717+
assert(kwds == NULL || PyDict_Check(kwds));
718+
716719
/* Special case: type(x) should return x->ob_type */
717-
if (metatype == &PyType_Type &&
718-
PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
719-
(kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) {
720-
PyObject *x = PyTuple_GET_ITEM(args, 0);
721-
Py_INCREF(x->ob_type);
722-
return (PyObject *) x->ob_type;
720+
{
721+
const int nargs = PyTuple_GET_SIZE(args);
722+
const int nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);
723+
724+
if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
725+
PyObject *x = PyTuple_GET_ITEM(args, 0);
726+
Py_INCREF(x->ob_type);
727+
return (PyObject *) x->ob_type;
728+
}
729+
730+
/* SF bug 475327 -- if that didn't trigger, we need 3
731+
arguments. but PyArg_ParseTupleAndKeywords below may give
732+
a msg saying type() needs exactly 3. */
733+
if (nargs + nkwds != 3) {
734+
PyErr_SetString(PyExc_TypeError,
735+
"type() takes 1 or 3 arguments");
736+
return NULL;
737+
}
723738
}
724739

725740
/* Check arguments: (name, bases, dict) */

0 commit comments

Comments
 (0)