Fix SF bug #486144: Uninitialized __slot__ vrbl is None.

There's now a new structmember code, T_OBJECT_EX, which is used for
all __slot__ variables (except __weakref__, which has special behavior
anyway).  This new code raises AttributeError when the variable is
NULL rather than converting NULL to None.
This commit is contained in:
Guido van Rossum 2001-12-04 16:23:42 +00:00
parent ebca9fc1ba
commit 6b70599450
3 changed files with 19 additions and 6 deletions

View file

@ -68,6 +68,10 @@ typedef struct PyMemberDef {
#define T_PSTRING_INPLACE 15
#endif /* macintosh */
#define T_OBJECT_EX 16 /* Like T_OBJECT, but raises AttributeError
when the value is NULL, instead of
converting to None. */
/* Flags */
#define READONLY 1
#define RO READONLY /* Shorthand */

View file

@ -978,19 +978,21 @@ def slots():
__slots__ = ['a']
x = C1()
verify(not hasattr(x, "__dict__"))
vereq(x.a, None)
verify(not hasattr(x, "a"))
x.a = 1
vereq(x.a, 1)
x.a = None
veris(x.a, None)
del x.a
vereq(x.a, None)
verify(not hasattr(x, "a"))
class C3(object):
__slots__ = ['a', 'b', 'c']
x = C3()
verify(not hasattr(x, "__dict__"))
verify(x.a is None)
verify(x.b is None)
verify(x.c is None)
verify(not hasattr(x, 'a'))
verify(not hasattr(x, 'b'))
verify(not hasattr(x, 'c'))
x.a = 1
x.b = 2
x.c = 3

View file

@ -129,6 +129,12 @@ PyMember_GetOne(char *addr, PyMemberDef *l)
v = Py_None;
Py_INCREF(v);
break;
case T_OBJECT_EX:
v = *(PyObject **)addr;
if (v == NULL)
PyErr_SetString(PyExc_AttributeError, l->name);
Py_XINCREF(v);
break;
default:
PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
v = NULL;
@ -175,7 +181,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
return -1;
}
if (v == NULL && l->type != T_OBJECT) {
if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) {
PyErr_SetString(PyExc_TypeError,
"can't delete numeric/char attribute");
return -1;
@ -246,6 +252,7 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
}
break;
case T_OBJECT:
case T_OBJECT_EX:
Py_XINCREF(v);
oldv = *(PyObject **)addr;
*(PyObject **)addr = v;