diff options
-rw-r--r-- | Include/Python.h | 4 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 18 | ||||
-rw-r--r-- | Objects/typeobject.c | 22 | ||||
-rw-r--r-- | Python/compile.c | 12 |
4 files changed, 49 insertions, 7 deletions
diff --git a/Include/Python.h b/Include/Python.h index 548ac75..ff21ad1 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -119,6 +119,10 @@ #include "abstract.h" +/* _Py_Mangle is defined in compile.c */ +extern DL_IMPORT(int) _Py_Mangle(char *p, char *name, \ + char *buffer, size_t maxlen); + /* PyArg_GetInt is deprecated and should not be used, use PyArg_Parse(). */ #define PyArg_GetInt(v, a) PyArg_Parse((v), "i", (a)) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 2129a7b..dca8ea1 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1060,6 +1060,24 @@ def slots(): vereq(x.b, 2) vereq(x.c, 3) + class C4(object): + """Validate name mangling""" + __slots__ = ['__a'] + def __init__(self, value): + self.__a = value + def get(self): + return self.__a + x = C4(5) + verify(not hasattr(x, '__dict__')) + verify(not hasattr(x, '__a')) + vereq(x.get(), 5) + try: + x.__a = 6 + except AttributeError: + pass + else: + raise TestFailed, "Double underscored names not mangled" + # Make sure slot names are proper identifiers try: class C(object): diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7918af0..47613f5 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1001,7 +1001,8 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) { PyObject *name, *bases, *dict; static char *kwlist[] = {"name", "bases", "dict", 0}; - PyObject *slots, *tmp; + static char buffer[256]; + PyObject *slots, *tmp, *newslots; PyTypeObject *type, *base, *tmptype, *winner; etype *et; PyMemberDef *mp; @@ -1115,6 +1116,25 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) return NULL; } } + + newslots = PyTuple_New(nslots); + if (newslots == NULL) + return NULL; + for (i = 0; i < nslots; i++) { + tmp = PyTuple_GET_ITEM(slots, i); + if (_Py_Mangle(PyString_AS_STRING(name), + PyString_AS_STRING(tmp), + buffer, sizeof(buffer))) + { + tmp = PyString_FromString(buffer); + } else { + Py_INCREF(tmp); + } + PyTuple_SET_ITEM(newslots, i, tmp); + } + Py_DECREF(slots); + slots = newslots; + } if (slots != NULL) { /* See if *this* class defines __getstate__ */ diff --git a/Python/compile.c b/Python/compile.c index b0e125d..fa53b1e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -928,8 +928,8 @@ com_addname(struct compiling *c, PyObject *v) return com_add(c, c->c_names, c->c_name_dict, v); } -static int -mangle(char *p, char *name, char *buffer, size_t maxlen) +int +_Py_Mangle(char *p, char *name, char *buffer, size_t maxlen) { /* Name mangling: __private becomes _classname__private. This is independent from how the name is used. */ @@ -963,7 +963,7 @@ com_addop_name(struct compiling *c, int op, char *name) int i; char buffer[MANGLE_LEN]; - if (mangle(c->c_private, name, buffer, sizeof(buffer))) + if (_Py_Mangle(c->c_private, name, buffer, sizeof(buffer))) name = buffer; if (name == NULL || (v = PyString_InternFromString(name)) == NULL) { c->c_errors++; @@ -1000,7 +1000,7 @@ com_addop_varname(struct compiling *c, int kind, char *name) int op = STOP_CODE; char buffer[MANGLE_LEN]; - if (mangle(c->c_private, name, buffer, sizeof(buffer))) + if (_Py_Mangle(c->c_private, name, buffer, sizeof(buffer))) name = buffer; if (name == NULL || (v = PyString_InternFromString(name)) == NULL) { c->c_errors++; @@ -4956,7 +4956,7 @@ symtable_lookup(struct symtable *st, char *name) PyObject *v; int flags; - if (mangle(st->st_private, name, buffer, sizeof(buffer))) + if (_Py_Mangle(st->st_private, name, buffer, sizeof(buffer))) name = buffer; v = PyDict_GetItemString(st->st_cur->ste_symbols, name); if (v == NULL) { @@ -4977,7 +4977,7 @@ symtable_add_def(struct symtable *st, char *name, int flag) char buffer[MANGLE_LEN]; int ret; - if (mangle(st->st_private, name, buffer, sizeof(buffer))) + if (_Py_Mangle(st->st_private, name, buffer, sizeof(buffer))) name = buffer; if ((s = PyString_InternFromString(name)) == NULL) return -1; |