mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
warnings.warn_explicit() did not have the proper TypeErrors in place to prevent
bus errors or SystemError being raised. As a side effect of fixing this, a bad DECREF that could be triggered when 'message' and 'category' were both None was fixed. Closes issue 3211. Thanks JP Calderone for the bug report.
This commit is contained in:
parent
80821f7cf4
commit
dea1b5653f
4 changed files with 34 additions and 5 deletions
|
@ -301,6 +301,21 @@ class WarnTests(unittest.TestCase):
|
||||||
warning_tests.__name__ = module_name
|
warning_tests.__name__ = module_name
|
||||||
sys.argv = argv
|
sys.argv = argv
|
||||||
|
|
||||||
|
def test_warn_explicit_type_errors(self):
|
||||||
|
# warn_explicit() shoud error out gracefully if it is given objects
|
||||||
|
# of the wrong types.
|
||||||
|
# lineno is expected to be an integer.
|
||||||
|
self.assertRaises(TypeError, self.module.warn_explicit,
|
||||||
|
None, UserWarning, None, None)
|
||||||
|
# Either 'message' needs to be an instance of Warning or 'category'
|
||||||
|
# needs to be a subclass.
|
||||||
|
self.assertRaises(TypeError, self.module.warn_explicit,
|
||||||
|
None, None, None, 1)
|
||||||
|
# 'registry' must be a dict or None.
|
||||||
|
self.assertRaises((TypeError, AttributeError),
|
||||||
|
self.module.warn_explicit,
|
||||||
|
None, Warning, None, 1, registry=42)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CWarnTests(BaseTest, WarnTests):
|
class CWarnTests(BaseTest, WarnTests):
|
||||||
|
|
|
@ -202,6 +202,7 @@ def warn(message, category=None, stacklevel=1):
|
||||||
|
|
||||||
def warn_explicit(message, category, filename, lineno,
|
def warn_explicit(message, category, filename, lineno,
|
||||||
module=None, registry=None, module_globals=None):
|
module=None, registry=None, module_globals=None):
|
||||||
|
lineno = int(lineno)
|
||||||
if module is None:
|
if module is None:
|
||||||
module = filename or "<unknown>"
|
module = filename or "<unknown>"
|
||||||
if module[-3:].lower() == ".py":
|
if module[-3:].lower() == ".py":
|
||||||
|
|
|
@ -25,6 +25,11 @@ What's New in Python 2.6 beta 1?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #3211: warnings.warn_explicit() did not guard against its 'registry'
|
||||||
|
argument being anything other than a dict or None. Also fixed a bug in error
|
||||||
|
handling when 'message' and 'category' were both set to None, triggering a
|
||||||
|
bus error.
|
||||||
|
|
||||||
- Issue #3100: Corrected a crash on deallocation of a subclassed weakref which
|
- Issue #3100: Corrected a crash on deallocation of a subclassed weakref which
|
||||||
holds the last (strong) reference to its referent.
|
holds the last (strong) reference to its referent.
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,11 @@ warn_explicit(PyObject *category, PyObject *message,
|
||||||
const char *action;
|
const char *action;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Normalize module. */
|
/* Normalize module. */
|
||||||
if (module == NULL) {
|
if (module == NULL) {
|
||||||
module = normalize_module(filename);
|
module = normalize_module(filename);
|
||||||
|
@ -303,6 +308,8 @@ warn_explicit(PyObject *category, PyObject *message,
|
||||||
else {
|
else {
|
||||||
text = message;
|
text = message;
|
||||||
message = PyObject_CallFunction(category, "O", message);
|
message = PyObject_CallFunction(category, "O", message);
|
||||||
|
if (message == NULL)
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
lineno_obj = PyInt_FromLong(lineno);
|
lineno_obj = PyInt_FromLong(lineno);
|
||||||
|
@ -314,7 +321,7 @@ warn_explicit(PyObject *category, PyObject *message,
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (registry != NULL) {
|
if ((registry != NULL) && (registry != Py_None)) {
|
||||||
rc = already_warned(registry, key, 0);
|
rc = already_warned(registry, key, 0);
|
||||||
if (rc == -1)
|
if (rc == -1)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -336,12 +343,13 @@ warn_explicit(PyObject *category, PyObject *message,
|
||||||
is "always". */
|
is "always". */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (strcmp(action, "always") != 0) {
|
if (strcmp(action, "always") != 0) {
|
||||||
if (registry != NULL && PyDict_SetItem(registry, key, Py_True) < 0)
|
if (registry != NULL && registry != Py_None &&
|
||||||
|
PyDict_SetItem(registry, key, Py_True) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
else if (strcmp(action, "ignore") == 0)
|
else if (strcmp(action, "ignore") == 0)
|
||||||
goto return_none;
|
goto return_none;
|
||||||
else if (strcmp(action, "once") == 0) {
|
else if (strcmp(action, "once") == 0) {
|
||||||
if (registry == NULL) {
|
if (registry == NULL || registry == Py_None) {
|
||||||
registry = get_once_registry();
|
registry = get_once_registry();
|
||||||
if (registry == NULL)
|
if (registry == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -351,7 +359,7 @@ warn_explicit(PyObject *category, PyObject *message,
|
||||||
}
|
}
|
||||||
else if (strcmp(action, "module") == 0) {
|
else if (strcmp(action, "module") == 0) {
|
||||||
/* registry[(text, category, 0)] = 1 */
|
/* registry[(text, category, 0)] = 1 */
|
||||||
if (registry != NULL)
|
if (registry != NULL && registry != Py_None)
|
||||||
rc = update_registry(registry, text, category, 0);
|
rc = update_registry(registry, text, category, 0);
|
||||||
}
|
}
|
||||||
else if (strcmp(action, "default") != 0) {
|
else if (strcmp(action, "default") != 0) {
|
||||||
|
@ -435,7 +443,7 @@ warn_explicit(PyObject *category, PyObject *message,
|
||||||
Py_XDECREF(text);
|
Py_XDECREF(text);
|
||||||
Py_XDECREF(lineno_obj);
|
Py_XDECREF(lineno_obj);
|
||||||
Py_DECREF(module);
|
Py_DECREF(module);
|
||||||
Py_DECREF(message);
|
Py_XDECREF(message);
|
||||||
return result; /* Py_None or NULL. */
|
return result; /* Py_None or NULL. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue