Skip to content

Commit 5127ed7

Browse files
Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(),
PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains() to check for and handle errors correctly.
1 parent 1e95340 commit 5127ed7

File tree

6 files changed

+83
-44
lines changed

6 files changed

+83
-44
lines changed

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ What's New in Python 2.7.11?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #24115: Update uses of PyObject_IsTrue(), PyObject_Not(),
14+
PyObject_IsInstance(), PyObject_RichCompareBool() and _PyDict_Contains()
15+
to check for and handle errors correctly.
16+
1317
- Issue #4753: On compilers where it is supported, use "computed gotos" for
1418
bytecode dispatch in the interpreter. This improves interpretation
1519
performance.

Modules/_json.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,9 @@ _parse_object_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
874874
int strict = PyObject_IsTrue(s->strict);
875875
Py_ssize_t next_idx;
876876

877+
if (strict < 0)
878+
return NULL;
879+
877880
pairs = PyList_New(0);
878881
if (pairs == NULL)
879882
return NULL;
@@ -997,6 +1000,9 @@ _parse_object_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ss
9971000
int strict = PyObject_IsTrue(s->strict);
9981001
Py_ssize_t next_idx;
9991002

1003+
if (strict < 0)
1004+
return NULL;
1005+
10001006
pairs = PyList_New(0);
10011007
if (pairs == NULL)
10021008
return NULL;
@@ -1466,6 +1472,7 @@ scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *n
14661472
Returns a new PyObject representation of the term.
14671473
*/
14681474
PyObject *res;
1475+
int strict;
14691476
char *str = PyString_AS_STRING(pystr);
14701477
Py_ssize_t length = PyString_GET_SIZE(pystr);
14711478
if (idx < 0) {
@@ -1479,10 +1486,11 @@ scan_once_str(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_t *n
14791486
switch (str[idx]) {
14801487
case '"':
14811488
/* string */
1489+
strict = PyObject_IsTrue(s->strict);
1490+
if (strict < 0)
1491+
return NULL;
14821492
return scanstring_str(pystr, idx + 1,
1483-
PyString_AS_STRING(s->encoding),
1484-
PyObject_IsTrue(s->strict),
1485-
next_idx_ptr);
1493+
PyString_AS_STRING(s->encoding), strict, next_idx_ptr);
14861494
case '{':
14871495
/* object */
14881496
if (Py_EnterRecursiveCall(" while decoding a JSON object "
@@ -1557,6 +1565,7 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
15571565
Returns a new PyObject representation of the term.
15581566
*/
15591567
PyObject *res;
1568+
int strict;
15601569
Py_UNICODE *str = PyUnicode_AS_UNICODE(pystr);
15611570
Py_ssize_t length = PyUnicode_GET_SIZE(pystr);
15621571
if (idx < 0) {
@@ -1570,9 +1579,10 @@ scan_once_unicode(PyScannerObject *s, PyObject *pystr, Py_ssize_t idx, Py_ssize_
15701579
switch (str[idx]) {
15711580
case '"':
15721581
/* string */
1573-
return scanstring_unicode(pystr, idx + 1,
1574-
PyObject_IsTrue(s->strict),
1575-
next_idx_ptr);
1582+
strict = PyObject_IsTrue(s->strict);
1583+
if (strict < 0)
1584+
return NULL;
1585+
return scanstring_unicode(pystr, idx + 1, strict, next_idx_ptr);
15761586
case '{':
15771587
/* object */
15781588
if (Py_EnterRecursiveCall(" while decoding a JSON object "
@@ -1825,14 +1835,19 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
18251835

18261836
PyEncoderObject *s;
18271837
PyObject *markers, *defaultfn, *encoder, *indent, *key_separator;
1828-
PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan;
1838+
PyObject *item_separator, *sort_keys, *skipkeys, *allow_nan_obj;
1839+
int allow_nan;
18291840

18301841
assert(PyEncoder_Check(self));
18311842
s = (PyEncoderObject *)self;
18321843

18331844
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO:make_encoder", kwlist,
18341845
&markers, &defaultfn, &encoder, &indent, &key_separator, &item_separator,
1835-
&sort_keys, &skipkeys, &allow_nan))
1846+
&sort_keys, &skipkeys, &allow_nan_obj))
1847+
return -1;
1848+
1849+
allow_nan = PyObject_IsTrue(allow_nan_obj);
1850+
if (allow_nan < 0)
18361851
return -1;
18371852

18381853
s->markers = markers;
@@ -1844,7 +1859,7 @@ encoder_init(PyObject *self, PyObject *args, PyObject *kwds)
18441859
s->sort_keys = sort_keys;
18451860
s->skipkeys = skipkeys;
18461861
s->fast_encode = (PyCFunction_Check(s->encoder) && PyCFunction_GetFunction(s->encoder) == (PyCFunction)py_encode_basestring_ascii);
1847-
s->allow_nan = PyObject_IsTrue(allow_nan);
1862+
s->allow_nan = allow_nan;
18481863

18491864
Py_INCREF(s->markers);
18501865
Py_INCREF(s->defaultfn);
@@ -2110,6 +2125,8 @@ encoder_listencode_dict(PyEncoderObject *s, PyObject *rval, PyObject *dct, Py_ss
21102125
if (it == NULL)
21112126
goto bail;
21122127
skipkeys = PyObject_IsTrue(s->skipkeys);
2128+
if (skipkeys < 0)
2129+
goto bail;
21132130
idx = 0;
21142131
while ((key = PyIter_Next(it)) != NULL) {
21152132
PyObject *encoded;

Modules/threadmodule.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -333,12 +333,18 @@ local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
333333
"_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
334334
};
335335

336-
if (type->tp_init == PyBaseObject_Type.tp_init
337-
&& ((args && PyObject_IsTrue(args))
338-
|| (kw && PyObject_IsTrue(kw)))) {
339-
PyErr_SetString(PyExc_TypeError,
340-
"Initialization arguments are not supported");
341-
return NULL;
336+
if (type->tp_init == PyBaseObject_Type.tp_init) {
337+
int rc = 0;
338+
if (args != NULL)
339+
rc = PyObject_IsTrue(args);
340+
if (rc == 0 && kw != NULL)
341+
rc = PyObject_IsTrue(kw);
342+
if (rc != 0) {
343+
if (rc > 0)
344+
PyErr_SetString(PyExc_TypeError,
345+
"Initialization arguments are not supported");
346+
return NULL;
347+
}
342348
}
343349

344350
self = (localobject *)type->tp_alloc(type, 0);

Objects/bytearrayobject.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,14 +1021,18 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op)
10211021
Py_buffer self_bytes, other_bytes;
10221022
PyObject *res;
10231023
Py_ssize_t minsize;
1024-
int cmp;
1024+
int cmp, rc;
10251025

10261026
/* Bytes can be compared to anything that supports the (binary)
10271027
buffer API. Except that a comparison with Unicode is always an
10281028
error, even if the comparison is for equality. */
10291029
#ifdef Py_USING_UNICODE
1030-
if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) ||
1031-
PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) {
1030+
rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type);
1031+
if (!rc)
1032+
rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type);
1033+
if (rc < 0)
1034+
return NULL;
1035+
if (rc) {
10321036
if (Py_BytesWarningFlag && op == Py_EQ) {
10331037
if (PyErr_WarnEx(PyExc_BytesWarning,
10341038
"Comparison between bytearray and string", 1))

Objects/setobject.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,9 +1548,15 @@ set_difference(PySetObject *so, PyObject *other)
15481548
if (PyDict_CheckExact(other)) {
15491549
while (set_next(so, &pos, &entry)) {
15501550
setentry entrycopy;
1551+
int rv;
15511552
entrycopy.hash = entry->hash;
15521553
entrycopy.key = entry->key;
1553-
if (!_PyDict_Contains(other, entry->key, entry->hash)) {
1554+
rv = _PyDict_Contains(other, entry->key, entry->hash);
1555+
if (rv < 0) {
1556+
Py_DECREF(result);
1557+
return NULL;
1558+
}
1559+
if (!rv) {
15541560
if (set_add_entry((PySetObject *)result, &entrycopy) == -1) {
15551561
Py_DECREF(result);
15561562
return NULL;
@@ -1793,7 +1799,8 @@ PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set.");
17931799
static PyObject *
17941800
set_richcompare(PySetObject *v, PyObject *w, int op)
17951801
{
1796-
PyObject *r1, *r2;
1802+
PyObject *r1;
1803+
int r2;
17971804

17981805
if(!PyAnySet_Check(w)) {
17991806
Py_INCREF(Py_NotImplemented);
@@ -1812,9 +1819,11 @@ set_richcompare(PySetObject *v, PyObject *w, int op)
18121819
r1 = set_richcompare(v, w, Py_EQ);
18131820
if (r1 == NULL)
18141821
return NULL;
1815-
r2 = PyBool_FromLong(PyObject_Not(r1));
1822+
r2 = PyObject_IsTrue(r1);
18161823
Py_DECREF(r1);
1817-
return r2;
1824+
if (r2 < 0)
1825+
return NULL;
1826+
return PyBool_FromLong(!r2);
18181827
case Py_LE:
18191828
return set_issubset(v, w);
18201829
case Py_GE:

Python/pythonrun.c

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,20 @@ add_flag(int flag, const char *envs)
137137
return flag;
138138
}
139139

140+
static int
141+
isatty_no_error(PyObject *sys_stream)
142+
{
143+
PyObject *sys_isatty = PyObject_CallMethod(sys_stream, "isatty", "");
144+
if (sys_isatty) {
145+
int isatty = PyObject_IsTrue(sys_isatty);
146+
Py_DECREF(sys_isatty);
147+
if (isatty >= 0)
148+
return isatty;
149+
}
150+
PyErr_Clear();
151+
return 0;
152+
}
153+
140154
void
141155
Py_InitializeEx(int install_sigs)
142156
{
@@ -150,7 +164,7 @@ Py_InitializeEx(int install_sigs)
150164
char *errors = NULL;
151165
int free_codeset = 0;
152166
int overridden = 0;
153-
PyObject *sys_stream, *sys_isatty;
167+
PyObject *sys_stream;
154168
#if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(CODESET)
155169
char *saved_locale, *loc_codeset;
156170
#endif
@@ -336,40 +350,25 @@ Py_InitializeEx(int install_sigs)
336350

337351
if (codeset) {
338352
sys_stream = PySys_GetObject("stdin");
339-
sys_isatty = PyObject_CallMethod(sys_stream, "isatty", "");
340-
if (!sys_isatty)
341-
PyErr_Clear();
342-
if ((overridden ||
343-
(sys_isatty && PyObject_IsTrue(sys_isatty))) &&
344-
PyFile_Check(sys_stream)) {
353+
if ((overridden || isatty_no_error(sys_stream)) &&
354+
PyFile_Check(sys_stream)) {
345355
if (!PyFile_SetEncodingAndErrors(sys_stream, icodeset, errors))
346356
Py_FatalError("Cannot set codeset of stdin");
347357
}
348-
Py_XDECREF(sys_isatty);
349358

350359
sys_stream = PySys_GetObject("stdout");
351-
sys_isatty = PyObject_CallMethod(sys_stream, "isatty", "");
352-
if (!sys_isatty)
353-
PyErr_Clear();
354-
if ((overridden ||
355-
(sys_isatty && PyObject_IsTrue(sys_isatty))) &&
356-
PyFile_Check(sys_stream)) {
360+
if ((overridden || isatty_no_error(sys_stream)) &&
361+
PyFile_Check(sys_stream)) {
357362
if (!PyFile_SetEncodingAndErrors(sys_stream, codeset, errors))
358363
Py_FatalError("Cannot set codeset of stdout");
359364
}
360-
Py_XDECREF(sys_isatty);
361365

362366
sys_stream = PySys_GetObject("stderr");
363-
sys_isatty = PyObject_CallMethod(sys_stream, "isatty", "");
364-
if (!sys_isatty)
365-
PyErr_Clear();
366-
if((overridden ||
367-
(sys_isatty && PyObject_IsTrue(sys_isatty))) &&
368-
PyFile_Check(sys_stream)) {
367+
if ((overridden || isatty_no_error(sys_stream)) &&
368+
PyFile_Check(sys_stream)) {
369369
if (!PyFile_SetEncodingAndErrors(sys_stream, codeset, errors))
370370
Py_FatalError("Cannot set codeset of stderr");
371371
}
372-
Py_XDECREF(sys_isatty);
373372

374373
if (free_codeset)
375374
free(codeset);

0 commit comments

Comments
 (0)