[Python-checkins] CVS: python/dist/src/Objects object.c,2.99,2.100

M.-A. Lemburg python-dev@python.org
Mon, 18 Sep 2000 09:21:00 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory slayer.i.sourceforge.net:/tmp/cvs-serv16900/Objects

Modified Files:
	object.c 
Log Message:
PyObject_SetAttr() and PyObject_GetAttr() now also accept Unicode
objects for the attribute name. Unicode objects are converted to
a string using the default encoding before trying the lookup.

Note that previously it was allowed to pass arbitrary objects as
attribute name in case the tp_getattro/setattro slots were defined.
This patch fixes this by applying an explicit string check first:
all uses of these slots expect string objects and do not check
for the type resulting in a core dump. The tp_getattro/setattro
are still useful as optimization for lookups using interned
string objects though.

This patch fixes bug #113829.

Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.99
retrieving revision 2.100
diff -C2 -r2.99 -r2.100
*** object.c	2000/09/01 23:29:27	2.99
--- object.c	2000/09/18 16:20:57	2.100
***************
*** 704,712 ****
  }
  
  PyObject *
  PyObject_GetAttr(PyObject *v, PyObject *name)
  {
! 	if (v->ob_type->tp_getattro != NULL)
! 		return (*v->ob_type->tp_getattro)(v, name);
  
  	if (!PyString_Check(name)) {
--- 704,723 ----
  }
  
+ /* Internal API needed by PyObject_GetAttr(): */
+ extern 
+ PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
+ 				  const char *errors);
+ 
  PyObject *
  PyObject_GetAttr(PyObject *v, PyObject *name)
  {
! 	/* The Unicode to string conversion is done here because the
! 	   existing tp_getattro slots expect a string object as name
! 	   and we wouldn't want to break those. */
! 	if (PyUnicode_Check(name)) {
! 		name = _PyUnicode_AsDefaultEncodedString(name, NULL);
! 		if (name == NULL)
! 			return NULL;
! 	}
  
  	if (!PyString_Check(name)) {
***************
*** 715,718 ****
--- 726,732 ----
  		return NULL;
  	}
+ 	if (v->ob_type->tp_getattro != NULL)
+ 		return (*v->ob_type->tp_getattro)(v, name);
+ 	else
  	return PyObject_GetAttrString(v, PyString_AS_STRING(name));
  }
***************
*** 734,751 ****
  {
  	int err;
! 	Py_INCREF(name);
! 	if (PyString_Check(name))
! 		PyString_InternInPlace(&name);
! 	if (v->ob_type->tp_setattro != NULL)
! 		err = (*v->ob_type->tp_setattro)(v, name, value);
! 	else if (PyString_Check(name)) {
! 		err = PyObject_SetAttrString(
! 			v, PyString_AS_STRING(name), value);
  	}
! 	else {
  		PyErr_SetString(PyExc_TypeError,
  				"attribute name must be string");
  		err = -1;
  	}
  	Py_DECREF(name);
  	return err;
--- 748,777 ----
  {
  	int err;
! 
! 	/* The Unicode to string conversion is done here because the
! 	   existing tp_setattro slots expect a string object as name
! 	   and we wouldn't want to break those. */
! 	if (PyUnicode_Check(name)) {
! 		name = PyUnicode_AsEncodedString(name, NULL, NULL);
! 		if (name == NULL)
! 			return -1;
  	}
! 	else
! 		Py_INCREF(name);
! 	
! 	if (!PyString_Check(name)){
  		PyErr_SetString(PyExc_TypeError,
  				"attribute name must be string");
  		err = -1;
  	}
+ 	else {
+ 		PyString_InternInPlace(&name);
+ 		if (v->ob_type->tp_setattro != NULL)
+ 			err = (*v->ob_type->tp_setattro)(v, name, value);
+ 		else
+ 			err = PyObject_SetAttrString(v, 
+ 				        PyString_AS_STRING(name), value);
+ 	}
+ 	
  	Py_DECREF(name);
  	return err;