changeset: 96375:82490d05f3b0 branch: 2.7 parent: 96355:418ab34fd1ce user: Serhiy Storchaka date: Sat May 30 17:45:12 2015 +0300 files: Misc/NEWS Modules/_json.c Modules/threadmodule.c Objects/bytearrayobject.c Objects/setobject.c Python/pythonrun.c description: Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly. diff -r 418ab34fd1ce -r 82490d05f3b0 Misc/NEWS --- a/Misc/NEWS Sat May 30 00:53:26 2015 +0300 +++ b/Misc/NEWS Sat May 30 17:45:12 2015 +0300 @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(), + PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() + to check for and handle errors correctly. + - Issue #4753: On compilers where it is supported, use "computed gotos" for bytecode dispatch in the interpreter. This improves interpretation performance. diff -r 418ab34fd1ce -r 82490d05f3b0 Modules/_json.c --- a/Modules/_json.c Sat May 30 00:53:26 2015 +0300 +++ b/Modules/_json.c Sat May 30 17:45:12 2015 +0300 @@ -874,6 +874,9 @@ int strict = PyObject_IsTrue(s->strict); Py_ssize_t next_idx; + if (strict < 0) + return NULL; + pairs = PyList_New(0); if (pairs == NULL) return NULL; @@ -997,6 +1000,9 @@ int strict = PyObject_IsTrue(s->strict); Py_ssize_t next_idx; + if (strict < 0) + return NULL; + pairs = PyList_New(0); if (pairs == NULL) return NULL; @@ -1466,6 +1472,7 @@ Returns a new PyObject representation of the term. */ PyObject *res; + int strict; char *str = PyString_AS_STRING(pystr); Py_ssize_t length = PyString_GET_SIZE(pystr); if (idx < 0) { @@ -1479,10 +1486,11 @@ switch (str[idx]) { case '"': /* string */ + strict = PyObject_IsTrue(s->strict); + if (strict < 0) + return NULL; return scanstring_str(pystr, idx + 1, - PyString_AS_STRING(s->encoding), - PyObject_IsTrue(s->strict), - next_idx_ptr); + PyString_AS_STRING(s->encoding), strict, next_idx_ptr); case '{': /* object */ if (Py_EnterRecursiveCall(" while decoding a JSON object " @@ -1557,6 +1565,7 @@ Returns a new PyObject representation of the term. */ PyObject *res; + int strict; Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr); Py_ssize_t length = PyUnicode_GET_SIZE(pystr); if (idx < 0) { @@ -1570,9 +1579,10 @@ switch (str[idx]) { case '"': /* string */ - return scanstring_unicode(pystr, idx + 1, - PyObject_IsTrue(s->strict), - next_idx_ptr); + strict = PyObject_IsTrue(s->strict); + if (strict < 0) + return NULL; + return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr); case '{': /* object */ if (Py_EnterRecursiveCall(" while decoding a JSON object " @@ -1825,14 +1835,19 @@ PyEncoderObject *s; PyObject *markers, *defaultfn, *encoder, *indent, *key_separator; - PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan; + PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan_obj; + int allow_nan; assert(PyEncoder_Check(self)); s = (PyEncoderObject *)self; if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist, &markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator, - &sort_keys, &skipkeys, &allow_nan)) + &sort_keys, &skipkeys, &allow_nan_obj)) + return -1; + + allow_nan = PyObject_IsTrue(allow_nan_obj); + if (allow_nan < 0) return -1; s->markers = markers; @@ -1844,7 +1859,7 @@ s->sort_keys = sort_keys; s->skipkeys = skipkeys; s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii); - s->allow_nan = PyObject_IsTrue(allow_nan); + s->allow_nan = allow_nan; Py_INCREF(s->markers); Py_INCREF(s->defaultfn); @@ -2110,6 +2125,8 @@ if (it == NULL) goto bail; skipkeys = PyObject_IsTrue(s->skipkeys); + if (skipkeys < 0) + goto bail; idx = 0; while ((key = PyIter_Next(it)) != NULL) { PyObject *encoded; diff -r 418ab34fd1ce -r 82490d05f3b0 Modules/threadmodule.c --- a/Modules/threadmodule.c Sat May 30 00:53:26 2015 +0300 +++ b/Modules/threadmodule.c Sat May 30 17:45:12 2015 +0300 @@ -333,12 +333,18 @@ "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O }; - if (type->tp_init == PyBaseObject_Type.tp_init - && ((args && PyObject_IsTrue(args)) - || (kw && PyObject_IsTrue(kw)))) { - PyErr_SetString(PyExc_TypeError, - "Initialization arguments are not supported"); - return NULL; + if (type->tp_init == PyBaseObject_Type.tp_init) { + int rc = 0; + if (args != NULL) + rc = PyObject_IsTrue(args); + if (rc == 0 && kw != NULL) + rc = PyObject_IsTrue(kw); + if (rc != 0) { + if (rc > 0) + PyErr_SetString(PyExc_TypeError, + "Initialization arguments are not supported"); + return NULL; + } } self = (localobject *)type->tp_alloc(type, 0); diff -r 418ab34fd1ce -r 82490d05f3b0 Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c Sat May 30 00:53:26 2015 +0300 +++ b/Objects/bytearrayobject.c Sat May 30 17:45:12 2015 +0300 @@ -1021,14 +1021,18 @@ Py_buffer self_bytes, other_bytes; PyObject *res; Py_ssize_t minsize; - int cmp; + int cmp, rc; /* Bytes can be compared to anything that supports the (binary) buffer API. Except that a comparison with Unicode is always an error, even if the comparison is for equality. */ #ifdef Py_USING_UNICODE - if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) { + rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type); + if (!rc) + rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type); + if (rc < 0) + return NULL; + if (rc) { if (Py_BytesWarningFlag && op == Py_EQ) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytearray and string", 1)) diff -r 418ab34fd1ce -r 82490d05f3b0 Objects/setobject.c --- a/Objects/setobject.c Sat May 30 00:53:26 2015 +0300 +++ b/Objects/setobject.c Sat May 30 17:45:12 2015 +0300 @@ -1548,9 +1548,15 @@ if (PyDict_CheckExact(other)) { while (set_next(so, &pos, &entry)) { setentry entrycopy; + int rv; entrycopy.hash = entry->hash; entrycopy.key = entry->key; - if (!_PyDict_Contains(other, entry->key, entry->hash)) { + rv = _PyDict_Contains(other, entry->key, entry->hash); + if (rv < 0) { + Py_DECREF(result); + return NULL; + } + if (!rv) { if (set_add_entry((PySetObject *)result, &entrycopy) == -1) { Py_DECREF(result); return NULL; @@ -1793,7 +1799,8 @@ static PyObject * set_richcompare(PySetObject *v, PyObject *w, int op) { - PyObject *r1, *r2; + PyObject *r1; + int r2; if(!PyAnySet_Check(w)) { Py_INCREF(Py_NotImplemented); @@ -1812,9 +1819,11 @@ r1 = set_richcompare(v, w, Py_EQ); if (r1 == NULL) return NULL; - r2 = PyBool_FromLong(PyObject_Not(r1)); + r2 = PyObject_IsTrue(r1); Py_DECREF(r1); - return r2; + if (r2 < 0) + return NULL; + return PyBool_FromLong(!r2); case Py_LE: return set_issubset(v, w); case Py_GE: diff -r 418ab34fd1ce -r 82490d05f3b0 Python/pythonrun.c --- a/Python/pythonrun.c Sat May 30 00:53:26 2015 +0300 +++ b/Python/pythonrun.c Sat May 30 17:45:12 2015 +0300 @@ -137,6 +137,20 @@ return flag; } +static int +isatty_no_error(PyObject *sys_stream) +{ + PyObject *sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); + if (sys_isatty) { + int isatty = PyObject_IsTrue(sys_isatty); + Py_DECREF(sys_isatty); + if (isatty >= 0) + return isatty; + } + PyErr_Clear(); + return 0; +} + void Py_InitializeEx(int install_sigs) { @@ -150,7 +164,7 @@ char *errors = NULL; int free_codeset = 0; int overridden = 0; - PyObject *sys_stream, *sys_isatty; + PyObject *sys_stream; #if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(CODESET) char *saved_locale, *loc_codeset; #endif @@ -336,40 +350,25 @@ if (codeset) { sys_stream = PySys_GetObject("stdin"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if ((overridden || - (sys_isatty && PyObject_IsTrue(sys_isatty))) && - PyFile_Check(sys_stream)) { + if ((overridden || isatty_no_error(sys_stream)) && + PyFile_Check(sys_stream)) { if (!PyFile_SetEncodingAndErrors(sys_stream, icodeset, errors)) Py_FatalError("Cannot set codeset of stdin"); } - Py_XDECREF(sys_isatty); sys_stream = PySys_GetObject("stdout"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if ((overridden || - (sys_isatty && PyObject_IsTrue(sys_isatty))) && - PyFile_Check(sys_stream)) { + if ((overridden || isatty_no_error(sys_stream)) && + PyFile_Check(sys_stream)) { if (!PyFile_SetEncodingAndErrors(sys_stream, codeset, errors)) Py_FatalError("Cannot set codeset of stdout"); } - Py_XDECREF(sys_isatty); sys_stream = PySys_GetObject("stderr"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if((overridden || - (sys_isatty && PyObject_IsTrue(sys_isatty))) && - PyFile_Check(sys_stream)) { + if ((overridden || isatty_no_error(sys_stream)) && + PyFile_Check(sys_stream)) { if (!PyFile_SetEncodingAndErrors(sys_stream, codeset, errors)) Py_FatalError("Cannot set codeset of stderr"); } - Py_XDECREF(sys_isatty); if (free_codeset) free(codeset);