diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index ca8e4d8b6d1..49cec1ec0ce 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -44,9 +44,9 @@ The following exceptions are used mostly as base classes for other exceptions. The base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes (for that, use :exc:`Exception`). If - :func:`bytes` or :func:`str` is called on an instance of this class, the - representation of the argument(s) to the instance are returned, or the empty - string when there were no arguments. + :func:`str` is called on an instance of this class, the representation of + the argument(s) to the instance are returned, or the empty string when + there were no arguments. .. attribute:: args diff --git a/Lib/sched.py b/Lib/sched.py index 3e41198c105..6c01e6968aa 100644 --- a/Lib/sched.py +++ b/Lib/sched.py @@ -35,9 +35,6 @@ from collections import namedtuple __all__ = ["scheduler"] class Event(namedtuple('Event', 'time, priority, action, argument, kwargs')): - def __init__(self, *args, **kwargs): - super(Event, self).__init__(*args, **kwargs) - self._scheduled = False def __eq__(s, o): return (s.time, s.priority) == (o.time, o.priority) def __ne__(s, o): return (s.time, s.priority) != (o.time, o.priority) def __lt__(s, o): return (s.time, s.priority) < (o.time, o.priority) @@ -62,7 +59,6 @@ class scheduler: """ event = Event(time, priority, action, argument, kwargs) - event._scheduled = True heapq.heappush(self._queue, event) return event # The ID @@ -85,9 +81,6 @@ class scheduler: self._queue.remove(event) heapq.heapify(self._queue) - def is_scheduled(self, event): - return event._scheduled - def empty(self): """Check whether the queue is empty.""" return not self._queue @@ -129,7 +122,6 @@ class scheduler: # Verify that the event was not removed or altered # by another thread after we last looked at q[0]. if event is checked_event: - event._scheduled = False action(*argument, **kwargs) delayfunc(0) # Let other threads run else: diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 4fbe5b45797..b1656bc4ff7 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -491,6 +491,17 @@ class ASTHelpers_Test(unittest.TestCase): self.assertEqual(ast.literal_eval('10 + 2j'), 10 + 2j) self.assertEqual(ast.literal_eval('1.5 - 2j'), 1.5 - 2j) + def test_bad_integer(self): + # issue13436: Bad error message with invalid numeric values + body = [ast.ImportFrom(module='time', + names=[ast.alias(name='sleep')], + level=None, + lineno=None, col_offset=None)] + mod = ast.Module(body) + with self.assertRaises(ValueError) as cm: + compile(mod, 'test', 'exec') + self.assertIn("invalid integer value: None", str(cm.exception)) + class ASTValidatorTests(unittest.TestCase): diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index b9e2f320082..ef5f8052aae 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -447,6 +447,16 @@ class EnvironTests(mapping_tests.BasicTestMappingProtocol): value_str = value.decode(sys.getfilesystemencoding(), 'surrogateescape') self.assertEqual(os.environ['bytes'], value_str) + def test_unset_error(self): + if sys.platform == "win32": + # an environment variable is limited to 32,767 characters + key = 'x' * 50000 + self.assertRaises(ValueError, os.environ.__delitem__, key) + else: + # "=" is not allowed in a variable name + key = 'key=' + self.assertRaises(OSError, os.environ.__delitem__, key) + class WalkTests(unittest.TestCase): """Tests for os.walk().""" diff --git a/Misc/NEWS b/Misc/NEWS index adc434c3cdb..f78a31eec70 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1? Core and Builtins ----------------- +- Issue #13436: Fix a bogus error message when an AST object was passed + an invalid integer value. + - Issue #13411: memoryview objects are now hashable when the underlying object is hashable. @@ -387,6 +390,11 @@ Core and Builtins Library ------- +- Issue #13458: Fix a memory leak in the ssl module when decoding a + certificate with a subjectAltName. Patch by Robert Xiao. + +- Issue #13415: os.unsetenv() doesn't ignore errors anymore. + - Issue #13245: sched.scheduler class constructor's timefunc and delayfunct parameters are now optional. scheduler.enter and scheduler.enterabs methods gained a new kwargs parameter. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index dcde4ff2afe..5772d901de7 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -707,6 +707,7 @@ _get_peer_alt_names (X509 *certificate) { } Py_DECREF(t); } + sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } BIO_free(biobuf); if (peer_alt_names != Py_None) { diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index fe924915ee7..094d0711726 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7749,61 +7749,28 @@ static PyObject *posix_putenv_garbage; static PyObject * posix_putenv(PyObject *self, PyObject *args) { -#ifdef MS_WINDOWS - PyObject *s1, *s2; - wchar_t *newenv; -#else - PyObject *os1, *os2; - char *s1, *s2; - char *newenv; - size_t len; -#endif PyObject *newstr = NULL; - #ifdef MS_WINDOWS + PyObject *os1, *os2; + wchar_t *newenv; + if (!PyArg_ParseTuple(args, "UU:putenv", - &s1, &s2)) + &os1, &os2)) return NULL; -#else - if (!PyArg_ParseTuple(args, - "O&O&:putenv", - PyUnicode_FSConverter, &os1, - PyUnicode_FSConverter, &os2)) - return NULL; - s1 = PyBytes_AsString(os1); - s2 = PyBytes_AsString(os2); -#endif -#if defined(PYOS_OS2) - if (stricmp(s1, "BEGINLIBPATH") == 0) { - APIRET rc; - - rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH); - if (rc != NO_ERROR) { - os2_error(rc); - goto error; - } - - } else if (stricmp(s1, "ENDLIBPATH") == 0) { - APIRET rc; - - rc = DosSetExtLIBPATH(s2, END_LIBPATH); - if (rc != NO_ERROR) { - os2_error(rc); - goto error; - } - } else { -#endif - /* XXX This can leak memory -- not easy to fix :-( */ - /* len includes space for a trailing \0; the size arg to - PyBytes_FromStringAndSize does not count that */ -#ifdef MS_WINDOWS - newstr = PyUnicode_FromFormat("%U=%U", s1, s2); + newstr = PyUnicode_FromFormat("%U=%U", os1, os2); if (newstr == NULL) { PyErr_NoMemory(); goto error; } + if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) { + PyErr_Format(PyExc_ValueError, + "the environment variable is longer than %u characters", + _MAX_ENV); + goto error; + } + newenv = PyUnicode_AsUnicode(newstr); if (newenv == NULL) goto error; @@ -7812,15 +7779,25 @@ posix_putenv(PyObject *self, PyObject *args) goto error; } #else - len = PyBytes_GET_SIZE(os1) + PyBytes_GET_SIZE(os2) + 2; - newstr = PyBytes_FromStringAndSize(NULL, (int)len - 1); + PyObject *os1, *os2; + char *s1, *s2; + char *newenv; + + if (!PyArg_ParseTuple(args, + "O&O&:putenv", + PyUnicode_FSConverter, &os1, + PyUnicode_FSConverter, &os2)) + return NULL; + s1 = PyBytes_AsString(os1); + s2 = PyBytes_AsString(os2); + + newstr = PyBytes_FromFormat("%s=%s", s1, s2); if (newstr == NULL) { PyErr_NoMemory(); goto error; } newenv = PyBytes_AS_STRING(newstr); - PyOS_snprintf(newenv, len, "%s=%s", s1, s2); if (putenv(newenv)) { posix_error(); goto error; @@ -7831,13 +7808,7 @@ posix_putenv(PyObject *self, PyObject *args) * this will cause previous value to be collected. This has to * happen after the real putenv() call because the old value * was still accessible until then. */ - if (PyDict_SetItem(posix_putenv_garbage, -#ifdef MS_WINDOWS - PyTuple_GET_ITEM(args, 0), -#else - os1, -#endif - newstr)) { + if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) { /* really not much we can do; just leak */ PyErr_Clear(); } @@ -7845,10 +7816,6 @@ posix_putenv(PyObject *self, PyObject *args) Py_DECREF(newstr); } -#if defined(PYOS_OS2) - } -#endif - #ifndef MS_WINDOWS Py_DECREF(os1); Py_DECREF(os2); @@ -7873,42 +7840,27 @@ Delete an environment variable."); static PyObject * posix_unsetenv(PyObject *self, PyObject *args) { -#ifdef MS_WINDOWS - char *s1; - - if (!PyArg_ParseTuple(args, "s:unsetenv", &s1)) - return NULL; -#else - PyObject *os1; - char *s1; + PyObject *name; + int err; if (!PyArg_ParseTuple(args, "O&:unsetenv", - PyUnicode_FSConverter, &os1)) + PyUnicode_FSConverter, &name)) return NULL; - s1 = PyBytes_AsString(os1); -#endif - unsetenv(s1); + err = unsetenv(PyBytes_AS_STRING(name)); + if (err) + return posix_error(); /* Remove the key from posix_putenv_garbage; * this will cause it to be collected. This has to * happen after the real unsetenv() call because the * old value was still accessible until then. */ - if (PyDict_DelItem(posix_putenv_garbage, -#ifdef MS_WINDOWS - PyTuple_GET_ITEM(args, 0) -#else - os1 -#endif - )) { + if (PyDict_DelItem(posix_putenv_garbage, name)) { /* really not much we can do; just leak */ PyErr_Clear(); } - -#ifndef MS_WINDOWS - Py_DECREF(os1); -#endif + Py_DECREF(name); Py_RETURN_NONE; } #endif /* unsetenv */ diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 651348eb9b0..07c06dea725 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -844,11 +844,7 @@ static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) { int i; if (!PyLong_Check(obj)) { - PyObject *s = PyObject_Repr(obj); - if (s == NULL) return 1; - PyErr_Format(PyExc_ValueError, "invalid integer value: %.400s", - PyBytes_AS_STRING(s)); - Py_DECREF(s); + PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); return 1; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 3cfb8a87aa6..8a101cf3b05 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -690,11 +690,7 @@ static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) { int i; if (!PyLong_Check(obj)) { - PyObject *s = PyObject_Repr(obj); - if (s == NULL) return 1; - PyErr_Format(PyExc_ValueError, "invalid integer value: %.400s", - PyBytes_AS_STRING(s)); - Py_DECREF(s); + PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); return 1; }