Subclasses of string can no longer be interned. The semantics of

interning were not clear here -- a subclass could be mutable, for
example -- and had bugs.  Explicitly interning a subclass of string
via intern() will raise a TypeError.  Internal operations that attempt
to intern a string subclass will have no effect.

Added a few tests to test_builtin that includes the old buggy code and
verifies that calls like PyObject_SetAttr() don't fail.  Perhaps these
tests should have gone in test_string.
This commit is contained in:
Jeremy Hylton 2004-08-07 19:20:05 +00:00
parent cbd81556bb
commit 4c989ddc9c
4 changed files with 40 additions and 22 deletions

View file

@ -4313,6 +4313,10 @@ PyString_InternInPlace(PyObject **p)
PyObject *t;
if (s == NULL || !PyString_Check(s))
Py_FatalError("PyString_InternInPlace: strings only please!");
/* If it's a string subclass, we don't really know what putting
it in the interned dict might do. */
if (!PyString_CheckExact(s))
return;
if (PyString_CHECK_INTERNED(s))
return;
if (interned == NULL) {
@ -4322,36 +4326,22 @@ PyString_InternInPlace(PyObject **p)
return;
}
}
if ((t = PyDict_GetItem(interned, (PyObject *)s)) != NULL) {
t = PyDict_GetItem(interned, (PyObject *)s);
if (t) {
Py_INCREF(t);
Py_DECREF(*p);
*p = t;
return;
}
/* Ensure that only true string objects appear in the intern dict */
if (!PyString_CheckExact(s)) {
t = PyString_FromStringAndSize(PyString_AS_STRING(s),
PyString_GET_SIZE(s));
if (t == NULL) {
PyErr_Clear();
return;
}
} else {
t = (PyObject*) s;
Py_INCREF(t);
}
if (PyDict_SetItem(interned, t, t) == 0) {
/* The two references in interned are not counted by
refcnt. The string deallocator will take care of this */
((PyObject *)t)->ob_refcnt-=2;
PyString_CHECK_INTERNED(t) = SSTATE_INTERNED_MORTAL;
Py_DECREF(*p);
*p = t;
if (PyDict_SetItem(interned, s, s) < 0) {
PyErr_Clear();
return;
}
Py_DECREF(t);
PyErr_Clear();
/* The two references in interned are not counted by refcnt.
The string deallocator will take care of this */
(*p)->ob_refcnt -= 2;
PyString_CHECK_INTERNED(s) = SSTATE_INTERNED_MORTAL;
}
void