Skip to content

Commit

Permalink
bpo-37994: Fix silencing all errors if an attribute lookup fails. (py…
Browse files Browse the repository at this point in the history
…thonGH-15630)

Only AttributeError should be silenced.
  • Loading branch information
serhiy-storchaka authored Sep 1, 2019
1 parent f02ea62 commit 41c57b3
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 127 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed silencing arbitrary errors if an attribute lookup fails in several
sites. Only AttributeError should be silenced.
5 changes: 4 additions & 1 deletion Modules/_csv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1382,7 +1382,10 @@ csv_writer(PyObject *module, PyObject *args, PyObject *keyword_args)
Py_DECREF(self);
return NULL;
}
self->write = _PyObject_GetAttrId(output_file, &PyId_write);
if (_PyObject_LookupAttrId(output_file, &PyId_write, &self->write) < 0) {
Py_DECREF(self);
return NULL;
}
if (self->write == NULL || !PyCallable_Check(self->write)) {
PyErr_SetString(PyExc_TypeError,
"argument 1 must have a \"write\" method");
Expand Down
21 changes: 10 additions & 11 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3607,24 +3607,24 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
_Py_IDENTIFIER(__getinitargs__);
_Py_IDENTIFIER(__getstate__);

getinitargs = _PyObject_GetAttrId(self, &PyId___getinitargs__);
if (_PyObject_LookupAttrId(self, &PyId___getinitargs__, &getinitargs) < 0) {
return NULL;
}
if (getinitargs != NULL) {
args = PyObject_CallNoArgs(getinitargs);
Py_DECREF(getinitargs);
if (args == NULL) {
return NULL;
}
}
else {
PyErr_Clear();

args = PyTuple_New(0);
if (args == NULL) {
return NULL;
}
}
if (args == NULL) {
return NULL;
}

getstate = _PyObject_GetAttrId(self, &PyId___getstate__);
if (_PyObject_LookupAttrId(self, &PyId___getstate__, &getstate) < 0) {
Py_DECREF(args);
return NULL;
}
if (getstate != NULL) {
state = PyObject_CallNoArgs(getstate);
Py_DECREF(getstate);
Expand All @@ -3635,7 +3635,6 @@ tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
}
else {
PyObject **dictptr;
PyErr_Clear();
state = Py_None;
dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr && PyDict_GET_SIZE(*dictptr)) {
Expand Down
13 changes: 7 additions & 6 deletions Modules/_pickle.c
Original file line number Diff line number Diff line change
Expand Up @@ -4383,7 +4383,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
_Py_IDENTIFIER(__reduce__);
_Py_IDENTIFIER(__reduce_ex__);


/* XXX: If the __reduce__ method is defined, __reduce_ex__ is
automatically defined as __reduce__. While this is convenient, this
make it impossible to know which method was actually called. Of
Expand All @@ -4404,14 +4403,15 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
}
}
else {
PickleState *st = _Pickle_GetGlobalState();

/* Check for a __reduce__ method. */
reduce_func = _PyObject_GetAttrId(obj, &PyId___reduce__);
if (_PyObject_LookupAttrId(obj, &PyId___reduce__, &reduce_func) < 0) {
goto error;
}
if (reduce_func != NULL) {
reduce_value = PyObject_CallNoArgs(reduce_func);
}
else {
PickleState *st = _Pickle_GetGlobalState();
PyErr_Format(st->PicklingError,
"can't pickle '%.200s' object: %R",
type->tp_name, obj);
Expand Down Expand Up @@ -6446,7 +6446,9 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
PyObject *extend_func;
_Py_IDENTIFIER(extend);

extend_func = _PyObject_GetAttrId(list, &PyId_extend);
if (_PyObject_LookupAttrId(list, &PyId_extend, &extend_func) < 0) {
return -1;
}
if (extend_func != NULL) {
slice = Pdata_poplist(self->stack, x);
if (!slice) {
Expand All @@ -6466,7 +6468,6 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
/* Even if the PEP 307 requires extend() and append() methods,
fall back on append() if the object has no extend() method
for backward compatibility. */
PyErr_Clear();
append_func = _PyObject_GetAttrId(list, &PyId_append);
if (append_func == NULL)
return -1;
Expand Down
7 changes: 4 additions & 3 deletions Modules/_threadmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1313,14 +1313,17 @@ static int
thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
PyObject *exc_traceback, PyObject *thread)
{
_Py_IDENTIFIER(name);
/* print(f"Exception in thread {thread.name}:", file=file) */
if (PyFile_WriteString("Exception in thread ", file) < 0) {
return -1;
}

PyObject *name = NULL;
if (thread != Py_None) {
name = PyObject_GetAttrString(thread, "name");
if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
return -1;
}
}
if (name != NULL) {
if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
Expand All @@ -1330,8 +1333,6 @@ thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
Py_DECREF(name);
}
else {
PyErr_Clear();

unsigned long ident = PyThread_get_thread_ident();
PyObject *str = PyUnicode_FromFormat("%lu", ident);
if (str != NULL) {
Expand Down
4 changes: 3 additions & 1 deletion Modules/pyexpat.c
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,9 @@ pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file)
PyObject *readmethod = NULL;
_Py_IDENTIFIER(read);

readmethod = _PyObject_GetAttrId(file, &PyId_read);
if (_PyObject_LookupAttrId(file, &PyId_read, &readmethod) < 0) {
return NULL;
}
if (readmethod == NULL) {
PyErr_SetString(PyExc_TypeError,
"argument must have 'read' attribute");
Expand Down
5 changes: 3 additions & 2 deletions Objects/bytearrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2061,9 +2061,10 @@ _common_reduce(PyByteArrayObject *self, int proto)
_Py_IDENTIFIER(__dict__);
char *buf;

dict = _PyObject_GetAttrId((PyObject *)self, &PyId___dict__);
if (_PyObject_LookupAttrId((PyObject *)self, &PyId___dict__, &dict) < 0) {
return NULL;
}
if (dict == NULL) {
PyErr_Clear();
dict = Py_None;
Py_INCREF(dict);
}
Expand Down
34 changes: 15 additions & 19 deletions Objects/descrobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1616,29 +1616,25 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
/* if no docstring given and the getter has one, use that one */
if ((doc == NULL || doc == Py_None) && fget != NULL) {
_Py_IDENTIFIER(__doc__);
PyObject *get_doc = _PyObject_GetAttrId(fget, &PyId___doc__);
if (get_doc) {
if (Py_TYPE(self) == &PyProperty_Type) {
Py_XSETREF(self->prop_doc, get_doc);
}
else {
/* If this is a property subclass, put __doc__
in dict of the subclass instance instead,
otherwise it gets shadowed by __doc__ in the
class's dict. */
int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
Py_DECREF(get_doc);
if (err < 0)
return -1;
}
self->getter_doc = 1;
PyObject *get_doc;
int rc = _PyObject_LookupAttrId(fget, &PyId___doc__, &get_doc);
if (rc <= 0) {
return rc;
}
else if (PyErr_ExceptionMatches(PyExc_Exception)) {
PyErr_Clear();
if (Py_TYPE(self) == &PyProperty_Type) {
Py_XSETREF(self->prop_doc, get_doc);
}
else {
return -1;
/* If this is a property subclass, put __doc__
in dict of the subclass instance instead,
otherwise it gets shadowed by __doc__ in the
class's dict. */
int err = _PyObject_SetAttrId((PyObject *)self, &PyId___doc__, get_doc);
Py_DECREF(get_doc);
if (err < 0)
return -1;
}
self->getter_doc = 1;
}

return 0;
Expand Down
6 changes: 4 additions & 2 deletions Objects/fileobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,10 @@ PyObject_AsFileDescriptor(PyObject *o)
if (PyLong_Check(o)) {
fd = _PyLong_AsInt(o);
}
else if ((meth = _PyObject_GetAttrId(o, &PyId_fileno)) != NULL)
{
else if (_PyObject_LookupAttrId(o, &PyId_fileno, &meth) < 0) {
return -1;
}
else if (meth != NULL) {
PyObject *fno = _PyObject_CallNoArg(meth);
Py_DECREF(meth);
if (fno == NULL)
Expand Down
5 changes: 3 additions & 2 deletions Objects/setobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1970,9 +1970,10 @@ set_reduce(PySetObject *so, PyObject *Py_UNUSED(ignored))
args = PyTuple_Pack(1, keys);
if (args == NULL)
goto done;
dict = _PyObject_GetAttrId((PyObject *)so, &PyId___dict__);
if (_PyObject_LookupAttrId((PyObject *)so, &PyId___dict__, &dict) < 0) {
goto done;
}
if (dict == NULL) {
PyErr_Clear();
dict = Py_None;
Py_INCREF(dict);
}
Expand Down
Loading

0 comments on commit 41c57b3

Please sign in to comment.