@@ -39,14 +39,15 @@ static PyObject *class_lookup
3939 Py_PROTO ((PyClassObject * , PyObject * , PyClassObject * * ) );
4040static PyObject * instance_getattr1 Py_PROTO ((PyInstanceObject * , PyObject * ) );
4141
42+ static PyObject * getattrstr , * setattrstr , * delattrstr ;
43+
4244PyObject *
4345PyClass_New (bases , dict , name )
4446 PyObject * bases ; /* NULL or tuple of classobjects! */
4547 PyObject * dict ;
4648 PyObject * name ;
4749{
4850 PyClassObject * op , * dummy ;
49- static PyObject * getattrstr , * setattrstr , * delattrstr ;
5051 static PyObject * docstr , * modstr , * namestr ;
5152 if (docstr == NULL ) {
5253 docstr = PyString_InternFromString ("__doc__" );
@@ -215,6 +216,72 @@ class_getattr(op, name)
215216 return v ;
216217}
217218
219+ static void
220+ set_slot (slot , v )
221+ PyObject * * slot ;
222+ PyObject * v ;
223+ {
224+ PyObject * temp = * slot ;
225+ Py_XINCREF (v );
226+ * slot = v ;
227+ Py_XDECREF (temp );
228+ }
229+
230+ static char *
231+ set_dict (c , v )
232+ PyClassObject * c ;
233+ PyObject * v ;
234+ {
235+ PyClassObject * dummy ;
236+
237+ if (v == NULL || !PyDict_Check (v ))
238+ return "__dict__ must be a dictionary object" ;
239+ set_slot (& c -> cl_dict , v );
240+
241+ set_slot (& c -> cl_getattr , class_lookup (c , getattrstr , & dummy ));
242+ set_slot (& c -> cl_setattr , class_lookup (c , setattrstr , & dummy ));
243+ set_slot (& c -> cl_delattr , class_lookup (c , delattrstr , & dummy ));
244+
245+ return "" ;
246+ }
247+
248+ static char *
249+ set_bases (c , v )
250+ PyClassObject * c ;
251+ PyObject * v ;
252+ {
253+ PyObject * temp ;
254+ int i , n ;
255+
256+ if (v == NULL || !PyTuple_Check (v ))
257+ return "__bases__ must be a tuple object" ;
258+ n = PyTuple_Size (v );
259+ for (i = 0 ; i < n ; i ++ ) {
260+ PyObject * x = PyTuple_GET_ITEM (v , i );
261+ if (!PyClass_Check (x ))
262+ return "__bases__ items must be classes" ;
263+ if (PyClass_IsSubclass (x , (PyObject * )c ))
264+ return "a __bases__ item causes an inheritance cycle" ;
265+ }
266+ set_slot (& c -> cl_bases , v );
267+ return "" ;
268+ }
269+
270+ static char *
271+ set_name (c , v )
272+ PyClassObject * c ;
273+ PyObject * v ;
274+ {
275+ PyObject * temp ;
276+
277+ if (v == NULL || !PyString_Check (v ))
278+ return "__name__ must be a string object" ;
279+ if (strlen (PyString_AS_STRING (v )) != PyString_GET_SIZE (v ))
280+ return "__name__ must not contain null bytes" ;
281+ set_slot (& c -> cl_name , v );
282+ return "" ;
283+ }
284+
218285static int
219286class_setattr (op , name , v )
220287 PyClassObject * op ;
@@ -231,17 +298,25 @@ class_setattr(op, name, v)
231298 if (sname [0 ] == '_' && sname [1 ] == '_' ) {
232299 int n = PyString_Size (name );
233300 if (sname [n - 1 ] == '_' && sname [n - 2 ] == '_' ) {
234- if (strcmp (sname , "__dict__" ) == 0 ||
235- strcmp (sname , "__bases__" ) == 0 ||
236- strcmp (sname , "__name__" ) == 0 ||
237- strcmp (sname , "__getattr__" ) == 0 ||
238- strcmp (sname , "__setattr__" ) == 0 ||
239- strcmp (sname , "__delattr__" ) == 0 )
240- {
241- /* XXX In unrestricted mode, we should
242- XXX allow this -- with a type check */
243- PyErr_SetString (PyExc_TypeError ,
244- "read-only special attribute" );
301+ char * err = NULL ;
302+ if (strcmp (sname , "__dict__" ) == 0 )
303+ err = set_dict (op , v );
304+ else if (strcmp (sname , "__bases__" ) == 0 )
305+ err = set_bases (op , v );
306+ else if (strcmp (sname , "__name__" ) == 0 )
307+ err = set_name (op , v );
308+ else if (strcmp (sname , "__getattr__" ) == 0 )
309+ set_slot (& op -> cl_getattr , v );
310+ else if (strcmp (sname , "__setattr__" ) == 0 )
311+ set_slot (& op -> cl_setattr , v );
312+ else if (strcmp (sname , "__delattr__" ) == 0 )
313+ set_slot (& op -> cl_delattr , v );
314+ /* For the last three, we fall through to update the
315+ dictionary as well. */
316+ if (err != NULL ) {
317+ if (* err == '\0' )
318+ return 0 ;
319+ PyErr_SetString (PyExc_TypeError , err );
245320 return -1 ;
246321 }
247322 }
0 commit comments