Skip to content

Commit 353053d

Browse files
[3.8] bpo-37994: Fix silencing all errors if an attribute lookup fails. (GH-15630) (GH-15635)
Only AttributeError should be silenced. (cherry picked from commit 41c57b3)
1 parent 6922b9e commit 353053d

File tree

14 files changed

+133
-126
lines changed

14 files changed

+133
-126
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed silencing arbitrary errors if an attribute lookup fails in several
2+
sites. Only AttributeError should be silenced.

Modules/_csv.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,10 @@ csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args)
13821382
Py_DECREF(self);
13831383
return NULL;
13841384
}
1385-
self->write = _PyObject_GetAttrId(output_file, &PyId_write);
1385+
if (_PyObject_LookupAttrId(output_file, &PyId_write, &self->write) < 0) {
1386+
Py_DECREF(self);
1387+
return NULL;
1388+
}
13861389
if (self->write == NULL || !PyCallable_Check(self->write)) {
13871390
PyErr_SetString(PyExc_TypeError,
13881391
"argument 1 must have a \"write\" method");

Modules/_datetimemodule.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3610,24 +3610,24 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
36103610
_Py_IDENTIFIER(__getinitargs__);
36113611
_Py_IDENTIFIER(__getstate__);
36123612

3613-
getinitargs = _PyObject_GetAttrId(self, &PyId___getinitargs__);
3613+
if (_PyObject_LookupAttrId(self, &PyId___getinitargs__, &getinitargs) < 0) {
3614+
return NULL;
3615+
}
36143616
if (getinitargs != NULL) {
36153617
args = _PyObject_CallNoArg(getinitargs);
36163618
Py_DECREF(getinitargs);
3617-
if (args == NULL) {
3618-
return NULL;
3619-
}
36203619
}
36213620
else {
3622-
PyErr_Clear();
3623-
36243621
args = PyTuple_New(0);
3625-
if (args == NULL) {
3626-
return NULL;
3627-
}
3622+
}
3623+
if (args == NULL) {
3624+
return NULL;
36283625
}
36293626

3630-
getstate = _PyObject_GetAttrId(self, &PyId___getstate__);
3627+
if (_PyObject_LookupAttrId(self, &PyId___getstate__, &getstate) < 0) {
3628+
Py_DECREF(args);
3629+
return NULL;
3630+
}
36313631
if (getstate != NULL) {
36323632
state = _PyObject_CallNoArg(getstate);
36333633
Py_DECREF(getstate);
@@ -3638,7 +3638,6 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
36383638
}
36393639
else {
36403640
PyObject **dictptr;
3641-
PyErr_Clear();
36423641
state = Py_None;
36433642
dictptr = _PyObject_GetDictPtr(self);
36443643
if (dictptr && *dictptr && PyDict_GET_SIZE(*dictptr)) {

Modules/_pickle.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4385,7 +4385,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
43854385
_Py_IDENTIFIER(__reduce__);
43864386
_Py_IDENTIFIER(__reduce_ex__);
43874387

4388-
43894388
/* XXX: If the __reduce__ method is defined, __reduce_ex__ is
43904389
automatically defined as __reduce__. While this is convenient, this
43914390
make it impossible to know which method was actually called. Of
@@ -4406,14 +4405,15 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
44064405
}
44074406
}
44084407
else {
4409-
PickleState *st = _Pickle_GetGlobalState();
4410-
44114408
/* Check for a __reduce__ method. */
4412-
reduce_func = _PyObject_GetAttrId(obj, &PyId___reduce__);
4409+
if (_PyObject_LookupAttrId(obj, &PyId___reduce__, &reduce_func) < 0) {
4410+
goto error;
4411+
}
44134412
if (reduce_func != NULL) {
44144413
reduce_value = _PyObject_CallNoArg(reduce_func);
44154414
}
44164415
else {
4416+
PickleState *st = _Pickle_GetGlobalState();
44174417
PyErr_Format(st->PicklingError,
44184418
"can't pickle '%.200s' object: %R",
44194419
type->tp_name, obj);
@@ -6448,7 +6448,9 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
64486448
PyObject *extend_func;
64496449
_Py_IDENTIFIER(extend);
64506450

6451-
extend_func = _PyObject_GetAttrId(list, &PyId_extend);
6451+
if (_PyObject_LookupAttrId(list, &PyId_extend, &extend_func) < 0) {
6452+
return -1;
6453+
}
64526454
if (extend_func != NULL) {
64536455
slice = Pdata_poplist(self->stack, x);
64546456
if (!slice) {
@@ -6468,7 +6470,6 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
64686470
/* Even if the PEP 307 requires extend() and append() methods,
64696471
fall back on append() if the object has no extend() method
64706472
for backward compatibility. */
6471-
PyErr_Clear();
64726473
append_func = _PyObject_GetAttrId(list, &PyId_append);
64736474
if (append_func == NULL)
64746475
return -1;

Modules/_threadmodule.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,14 +1305,17 @@ static int
13051305
thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
13061306
PyObject *exc_traceback, PyObject *thread)
13071307
{
1308+
_Py_IDENTIFIER(name);
13081309
/* print(f"Exception in thread {thread.name}:", file=file) */
13091310
if (PyFile_WriteString("Exception in thread ", file) < 0) {
13101311
return -1;
13111312
}
13121313

13131314
PyObject *name = NULL;
13141315
if (thread != Py_None) {
1315-
name = PyObject_GetAttrString(thread, "name");
1316+
if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1317+
return -1;
1318+
}
13161319
}
13171320
if (name != NULL) {
13181321
if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
@@ -1322,8 +1325,6 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
13221325
Py_DECREF(name);
13231326
}
13241327
else {
1325-
PyErr_Clear();
1326-
13271328
unsigned long ident = PyThread_get_thread_ident();
13281329
PyObject *str = PyUnicode_FromFormat("%lu", ident);
13291330
if (str != NULL) {

Modules/pyexpat.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,9 @@ pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file)
810810
PyObject *readmethod = NULL;
811811
_Py_IDENTIFIER(read);
812812

813-
readmethod = _PyObject_GetAttrId(file, &PyId_read);
813+
if (_PyObject_LookupAttrId(file, &PyId_read, &readmethod) < 0) {
814+
return NULL;
815+
}
814816
if (readmethod == NULL) {
815817
PyErr_SetString(PyExc_TypeError,
816818
"argument must have 'read' attribute");

Objects/bytearrayobject.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,9 +2063,10 @@ _common_reduce(PyByteArrayObject *self, int proto)
20632063
_Py_IDENTIFIER(__dict__);
20642064
char *buf;
20652065

2066-
dict = _PyObject_GetAttrId((PyObject *)self, &PyId___dict__);
2066+
if (_PyObject_LookupAttrId((PyObject *)self, &PyId___dict__, &dict) < 0) {
2067+
return NULL;
2068+
}
20672069
if (dict == NULL) {
2068-
PyErr_Clear();
20692070
dict = Py_None;
20702071
Py_INCREF(dict);
20712072
}

Objects/descrobject.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,29 +1622,25 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
16221622
/* if no docstring given and the getter has one, use that one */
16231623
if ((doc == NULL || doc == Py_None) && fget != NULL) {
16241624
_Py_IDENTIFIER(__doc__);
1625-
PyObject *get_doc = _PyObject_GetAttrId(fget, &PyId___doc__);
1626-
if (get_doc) {
1627-
if (Py_TYPE(self) == &PyProperty_Type) {
1628-
Py_XSETREF(self->prop_doc, get_doc);
1629-
}
1630-
else {
1631-
/* If this is a property subclass, put __doc__
1632-
in dict of the subclass instance instead,
1633-
otherwise it gets shadowed by __doc__ in the
1634-
class's dict. */
1635-
int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1636-
Py_DECREF(get_doc);
1637-
if (err < 0)
1638-
return -1;
1639-
}
1640-
self->getter_doc = 1;
1625+
PyObject *get_doc;
1626+
int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1627+
if (rc <= 0) {
1628+
return rc;
16411629
}
1642-
else if (PyErr_ExceptionMatches(PyExc_Exception)) {
1643-
PyErr_Clear();
1630+
if (Py_TYPE(self) == &PyProperty_Type) {
1631+
Py_XSETREF(self->prop_doc, get_doc);
16441632
}
16451633
else {
1646-
return -1;
1634+
/* If this is a property subclass, put __doc__
1635+
in dict of the subclass instance instead,
1636+
otherwise it gets shadowed by __doc__ in the
1637+
class's dict. */
1638+
int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1639+
Py_DECREF(get_doc);
1640+
if (err < 0)
1641+
return -1;
16471642
}
1643+
self->getter_doc = 1;
16481644
}
16491645

16501646
return 0;

Objects/fileobject.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,10 @@ PyObject_AsFileDescriptor(PyObject *o)
185185
if (PyLong_Check(o)) {
186186
fd = _PyLong_AsInt(o);
187187
}
188-
else if ((meth = _PyObject_GetAttrId(o, &PyId_fileno)) != NULL)
189-
{
188+
else if (_PyObject_LookupAttrId(o, &PyId_fileno, &meth) < 0) {
189+
return -1;
190+
}
191+
else if (meth != NULL) {
190192
PyObject *fno = _PyObject_CallNoArg(meth);
191193
Py_DECREF(meth);
192194
if (fno == NULL)

Objects/setobject.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,9 +1954,10 @@ set_reduce(PySetObject *so, PyObject *Py_UNUSED(ignored))
19541954
args = PyTuple_Pack(1, keys);
19551955
if (args == NULL)
19561956
goto done;
1957-
dict = _PyObject_GetAttrId((PyObject *)so, &PyId___dict__);
1957+
if (_PyObject_LookupAttrId((PyObject *)so, &PyId___dict__, &dict) < 0) {
1958+
goto done;
1959+
}
19581960
if (dict == NULL) {
1959-
PyErr_Clear();
19601961
dict = Py_None;
19611962
Py_INCREF(dict);
19621963
}

0 commit comments

Comments
 (0)