Commit db734912 authored by Brett Cannon's avatar Brett Cannon

Merged revisions 64549 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r64549 | brett.cannon | 2008-06-26 17:31:13 -0700 (Thu, 26 Jun 2008) | 7 lines

  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.
........
parent 429ef650
...@@ -301,6 +301,21 @@ class WarnTests(unittest.TestCase): ...@@ -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):
......
...@@ -188,6 +188,7 @@ def warn(message, category=None, stacklevel=1): ...@@ -188,6 +188,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":
......
...@@ -27,6 +27,11 @@ What's new in Python 3.0b1? ...@@ -27,6 +27,11 @@ What's new in Python 3.0b1?
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.
......
...@@ -280,6 +280,11 @@ warn_explicit(PyObject *category, PyObject *message, ...@@ -280,6 +280,11 @@ warn_explicit(PyObject *category, PyObject *message,
PyObject *item = Py_None; PyObject *item = Py_None;
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) {
...@@ -303,6 +308,8 @@ warn_explicit(PyObject *category, PyObject *message, ...@@ -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 = PyLong_FromLong(lineno); lineno_obj = PyLong_FromLong(lineno);
...@@ -314,7 +321,7 @@ warn_explicit(PyObject *category, PyObject *message, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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. */
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment