[Python-3000-checkins] r64552 - in python/branches/py3k: Lib/test/test_warnings.py Lib/warnings.py Misc/NEWS Python/_warnings.c

brett.cannon python-3000-checkins at python.org
Fri Jun 27 02:52:16 CEST 2008


Author: brett.cannon
Date: Fri Jun 27 02:52:15 2008
New Revision: 64552

Log:
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.
........


Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Lib/test/test_warnings.py
   python/branches/py3k/Lib/warnings.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Python/_warnings.c

Modified: python/branches/py3k/Lib/test/test_warnings.py
==============================================================================
--- python/branches/py3k/Lib/test/test_warnings.py	(original)
+++ python/branches/py3k/Lib/test/test_warnings.py	Fri Jun 27 02:52:15 2008
@@ -301,6 +301,21 @@
             warning_tests.__name__ = module_name
             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):

Modified: python/branches/py3k/Lib/warnings.py
==============================================================================
--- python/branches/py3k/Lib/warnings.py	(original)
+++ python/branches/py3k/Lib/warnings.py	Fri Jun 27 02:52:15 2008
@@ -188,6 +188,7 @@
 
 def warn_explicit(message, category, filename, lineno,
                   module=None, registry=None, module_globals=None):
+    lineno = int(lineno)
     if module is None:
         module = filename or "<unknown>"
         if module[-3:].lower() == ".py":

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Fri Jun 27 02:52:15 2008
@@ -27,6 +27,11 @@
 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
   holds the last (strong) reference to its referent.
 

Modified: python/branches/py3k/Python/_warnings.c
==============================================================================
--- python/branches/py3k/Python/_warnings.c	(original)
+++ python/branches/py3k/Python/_warnings.c	Fri Jun 27 02:52:15 2008
@@ -280,6 +280,11 @@
     PyObject *item = Py_None;
     const char *action;
     int rc;
+    
+    if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
+        PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
+        return NULL;
+    }
 
     /* Normalize module. */
     if (module == NULL) {
@@ -303,6 +308,8 @@
     else {
         text = message;
         message = PyObject_CallFunction(category, "O", message);
+        if (message == NULL)
+            goto cleanup;
     }
 
     lineno_obj = PyLong_FromLong(lineno);
@@ -314,7 +321,7 @@
     if (key == NULL)
         goto cleanup;
 
-    if (registry != NULL) {
+    if ((registry != NULL) && (registry != Py_None)) {
         rc = already_warned(registry, key, 0);
         if (rc == -1)
             goto cleanup;
@@ -336,12 +343,13 @@
        is "always". */
     rc = 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;
         else if (strcmp(action, "ignore") == 0)
             goto return_none;
         else if (strcmp(action, "once") == 0) {
-            if (registry == NULL) {
+            if (registry == NULL || registry == Py_None) {
                 registry = get_once_registry();
                 if (registry == NULL)
                     goto cleanup;
@@ -351,7 +359,7 @@
         }
         else if (strcmp(action, "module") == 0) {
             /* registry[(text, category, 0)] = 1 */
-            if (registry != NULL)
+            if (registry != NULL && registry != Py_None)
                 rc = update_registry(registry, text, category, 0); 
         }
         else if (strcmp(action, "default") != 0) {
@@ -435,7 +443,7 @@
     Py_XDECREF(text);
     Py_XDECREF(lineno_obj);
     Py_DECREF(module);
-    Py_DECREF(message);
+    Py_XDECREF(message);
     return result;  /* Py_None or NULL. */
 }
 


More information about the Python-3000-checkins mailing list