]> granicus.if.org Git - python/commitdiff
check for string attribute names in old-style classes (closes #14334)
authorBenjamin Peterson <benjamin@python.org>
Fri, 16 Mar 2012 15:58:46 +0000 (10:58 -0500)
committerBenjamin Peterson <benjamin@python.org>
Fri, 16 Mar 2012 15:58:46 +0000 (10:58 -0500)
Lib/test/test_class.py
Misc/NEWS
Objects/classobject.c

index db75b934795155d3e1354908ab756c43f7b13617..e5cdf088f42ea75de1ea846b3f56765f2d4d2e46 100644 (file)
@@ -628,6 +628,13 @@ class ClassTests(unittest.TestCase):
         a = A(hash(A.f.im_func)^(-1))
         hash(a.f)
 
+    def testAttrSlots(self):
+        class C:
+            pass
+        for c in C, C():
+            self.assertRaises(TypeError, type(c).__getattribute__, c, [])
+            self.assertRaises(TypeError, type(c).__setattr__, c, [], [])
+
 def test_main():
     with test_support.check_py3k_warnings(
             (".+__(get|set|del)slice__ has been removed", DeprecationWarning),
index 40c88d9572c672a3853da137fd4f401cbcbe7cac..471051f665170e3c28519ef6641369337888d7f3 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,7 +10,8 @@ Core and Builtins
 -----------------
 
 - Issue #14334: Prevent in a segfault in type.__getattribute__ when it was not
-  passed strings.
+  passed strings. Also fix segfaults in the __getattribute__ and __setattr__
+  methods of old-style classes.
 
 - Issue #14161: fix the __repr__ of file objects to escape the file name.
 
index 161906ae5d19b32f30d5c6e89b22528a1922de18..2c9c21694e487b56acf5b34fb917d095281f38c6 100644 (file)
@@ -225,10 +225,16 @@ static PyObject *
 class_getattr(register PyClassObject *op, PyObject *name)
 {
     register PyObject *v;
-    register char *sname = PyString_AsString(name);
+    register char *sname;
     PyClassObject *klass;
     descrgetfunc f;
 
+    if (!PyString_Check(name)) {
+        PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
+        return NULL;
+    }
+
+    sname = PyString_AsString(name);
     if (sname[0] == '_' && sname[1] == '_') {
         if (strcmp(sname, "__dict__") == 0) {
             if (PyEval_GetRestricted()) {
@@ -336,6 +342,10 @@ class_setattr(PyClassObject *op, PyObject *name, PyObject *v)
                    "classes are read-only in restricted mode");
         return -1;
     }
+    if (!PyString_Check(name)) {
+        PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
+        return -1;
+    }
     sname = PyString_AsString(name);
     if (sname[0] == '_' && sname[1] == '_') {
         Py_ssize_t n = PyString_Size(name);
@@ -699,7 +709,14 @@ static PyObject *
 instance_getattr1(register PyInstanceObject *inst, PyObject *name)
 {
     register PyObject *v;
-    register char *sname = PyString_AsString(name);
+    register char *sname;
+
+    if (!PyString_Check(name)) {
+        PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
+        return NULL;
+    }
+
+    sname = PyString_AsString(name);
     if (sname[0] == '_' && sname[1] == '_') {
         if (strcmp(sname, "__dict__") == 0) {
             if (PyEval_GetRestricted()) {
@@ -810,7 +827,14 @@ static int
 instance_setattr(PyInstanceObject *inst, PyObject *name, PyObject *v)
 {
     PyObject *func, *args, *res, *tmp;
-    char *sname = PyString_AsString(name);
+    char *sname;
+
+    if (!PyString_Check(name)) {
+        PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
+        return -1;
+    }
+
+    sname = PyString_AsString(name);
     if (sname[0] == '_' && sname[1] == '_') {
         Py_ssize_t n = PyString_Size(name);
         if (sname[n-1] == '_' && sname[n-2] == '_') {