Skip to content

Commit 41c57b3

Browse files
bpo-37994: Fix silencing all errors if an attribute lookup fails. (pythonGH-15630)
Only AttributeError should be silenced.
1 parent f02ea62 commit 41c57b3

14 files changed

+134
-127
lines changed
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

+4-1
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

+10-11
Original file line numberDiff line numberDiff line change
@@ -3607,24 +3607,24 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
36073607
_Py_IDENTIFIER(__getinitargs__);
36083608
_Py_IDENTIFIER(__getstate__);
36093609

3610-
getinitargs = _PyObject_GetAttrId(self, &PyId___getinitargs__);
3610+
if (_PyObject_LookupAttrId(self, &PyId___getinitargs__, &getinitargs) < 0) {
3611+
return NULL;
3612+
}
36113613
if (getinitargs != NULL) {
36123614
args = PyObject_CallNoArgs(getinitargs);
36133615
Py_DECREF(getinitargs);
3614-
if (args == NULL) {
3615-
return NULL;
3616-
}
36173616
}
36183617
else {
3619-
PyErr_Clear();
3620-
36213618
args = PyTuple_New(0);
3622-
if (args == NULL) {
3623-
return NULL;
3624-
}
3619+
}
3620+
if (args == NULL) {
3621+
return NULL;
36253622
}
36263623

3627-
getstate = _PyObject_GetAttrId(self, &PyId___getstate__);
3624+
if (_PyObject_LookupAttrId(self, &PyId___getstate__, &getstate) < 0) {
3625+
Py_DECREF(args);
3626+
return NULL;
3627+
}
36283628
if (getstate != NULL) {
36293629
state = PyObject_CallNoArgs(getstate);
36303630
Py_DECREF(getstate);
@@ -3635,7 +3635,6 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
36353635
}
36363636
else {
36373637
PyObject **dictptr;
3638-
PyErr_Clear();
36393638
state = Py_None;
36403639
dictptr = _PyObject_GetDictPtr(self);
36413640
if (dictptr && *dictptr && PyDict_GET_SIZE(*dictptr)) {

Modules/_pickle.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -4383,7 +4383,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
43834383
_Py_IDENTIFIER(__reduce__);
43844384
_Py_IDENTIFIER(__reduce_ex__);
43854385

4386-
43874386
/* XXX: If the __reduce__ method is defined, __reduce_ex__ is
43884387
automatically defined as __reduce__. While this is convenient, this
43894388
make it impossible to know which method was actually called. Of
@@ -4404,14 +4403,15 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
44044403
}
44054404
}
44064405
else {
4407-
PickleState *st = _Pickle_GetGlobalState();
4408-
44094406
/* Check for a __reduce__ method. */
4410-
reduce_func = _PyObject_GetAttrId(obj, &PyId___reduce__);
4407+
if (_PyObject_LookupAttrId(obj, &PyId___reduce__, &reduce_func) < 0) {
4408+
goto error;
4409+
}
44114410
if (reduce_func != NULL) {
44124411
reduce_value = PyObject_CallNoArgs(reduce_func);
44134412
}
44144413
else {
4414+
PickleState *st = _Pickle_GetGlobalState();
44154415
PyErr_Format(st->PicklingError,
44164416
"can't pickle '%.200s' object: %R",
44174417
type->tp_name, obj);
@@ -6446,7 +6446,9 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
64466446
PyObject *extend_func;
64476447
_Py_IDENTIFIER(extend);
64486448

6449-
extend_func = _PyObject_GetAttrId(list, &PyId_extend);
6449+
if (_PyObject_LookupAttrId(list, &PyId_extend, &extend_func) < 0) {
6450+
return -1;
6451+
}
64506452
if (extend_func != NULL) {
64516453
slice = Pdata_poplist(self->stack, x);
64526454
if (!slice) {
@@ -6466,7 +6468,6 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
64666468
/* Even if the PEP 307 requires extend() and append() methods,
64676469
fall back on append() if the object has no extend() method
64686470
for backward compatibility. */
6469-
PyErr_Clear();
64706471
append_func = _PyObject_GetAttrId(list, &PyId_append);
64716472
if (append_func == NULL)
64726473
return -1;

Modules/_threadmodule.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -1313,14 +1313,17 @@ static int
13131313
thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
13141314
PyObject *exc_traceback, PyObject *thread)
13151315
{
1316+
_Py_IDENTIFIER(name);
13161317
/* print(f"Exception in thread {thread.name}:", file=file) */
13171318
if (PyFile_WriteString("Exception in thread ", file) < 0) {
13181319
return -1;
13191320
}
13201321

13211322
PyObject *name = NULL;
13221323
if (thread != Py_None) {
1323-
name = PyObject_GetAttrString(thread, "name");
1324+
if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1325+
return -1;
1326+
}
13241327
}
13251328
if (name != NULL) {
13261329
if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
@@ -1330,8 +1333,6 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
13301333
Py_DECREF(name);
13311334
}
13321335
else {
1333-
PyErr_Clear();
1334-
13351336
unsigned long ident = PyThread_get_thread_ident();
13361337
PyObject *str = PyUnicode_FromFormat("%lu", ident);
13371338
if (str != NULL) {

Modules/pyexpat.c

+3-1
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

+3-2
Original file line numberDiff line numberDiff line change
@@ -2061,9 +2061,10 @@ _common_reduce(PyByteArrayObject *self, int proto)
20612061
_Py_IDENTIFIER(__dict__);
20622062
char *buf;
20632063

2064-
dict = _PyObject_GetAttrId((PyObject *)self, &PyId___dict__);
2064+
if (_PyObject_LookupAttrId((PyObject *)self, &PyId___dict__, &dict) < 0) {
2065+
return NULL;
2066+
}
20652067
if (dict == NULL) {
2066-
PyErr_Clear();
20672068
dict = Py_None;
20682069
Py_INCREF(dict);
20692070
}

Objects/descrobject.c

+15-19
Original file line numberDiff line numberDiff line change
@@ -1616,29 +1616,25 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
16161616
/* if no docstring given and the getter has one, use that one */
16171617
if ((doc == NULL || doc == Py_None) && fget != NULL) {
16181618
_Py_IDENTIFIER(__doc__);
1619-
PyObject *get_doc = _PyObject_GetAttrId(fget, &PyId___doc__);
1620-
if (get_doc) {
1621-
if (Py_TYPE(self) == &PyProperty_Type) {
1622-
Py_XSETREF(self->prop_doc, get_doc);
1623-
}
1624-
else {
1625-
/* If this is a property subclass, put __doc__
1626-
in dict of the subclass instance instead,
1627-
otherwise it gets shadowed by __doc__ in the
1628-
class's dict. */
1629-
int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1630-
Py_DECREF(get_doc);
1631-
if (err < 0)
1632-
return -1;
1633-
}
1634-
self->getter_doc = 1;
1619+
PyObject *get_doc;
1620+
int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
1621+
if (rc <= 0) {
1622+
return rc;
16351623
}
1636-
else if (PyErr_ExceptionMatches(PyExc_Exception)) {
1637-
PyErr_Clear();
1624+
if (Py_TYPE(self) == &PyProperty_Type) {
1625+
Py_XSETREF(self->prop_doc, get_doc);
16381626
}
16391627
else {
1640-
return -1;
1628+
/* If this is a property subclass, put __doc__
1629+
in dict of the subclass instance instead,
1630+
otherwise it gets shadowed by __doc__ in the
1631+
class's dict. */
1632+
int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
1633+
Py_DECREF(get_doc);
1634+
if (err < 0)
1635+
return -1;
16411636
}
1637+
self->getter_doc = 1;
16421638
}
16431639

16441640
return 0;

Objects/fileobject.c

+4-2
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

+3-2
Original file line numberDiff line numberDiff line change
@@ -1970,9 +1970,10 @@ set_reduce(PySetObject *so, PyObject *Py_UNUSED(ignored))
19701970
args = PyTuple_Pack(1, keys);
19711971
if (args == NULL)
19721972
goto done;
1973-
dict = _PyObject_GetAttrId((PyObject *)so, &PyId___dict__);
1973+
if (_PyObject_LookupAttrId((PyObject *)so, &PyId___dict__, &dict) < 0) {
1974+
goto done;
1975+
}
19741976
if (dict == NULL) {
1975-
PyErr_Clear();
19761977
dict = Py_None;
19771978
Py_INCREF(dict);
19781979
}

0 commit comments

Comments
 (0)