Skip to content

Commit be6ec44

Browse files
bpo-35444: Fix error handling when fail to look up builtin "getattr". (GH-11047) (GH-11107) (GH-11108)
(cherry picked from commit bb86bf4) (cherry picked from commit 3cae16d) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent f74cabd commit be6ec44

File tree

7 files changed

+29
-30
lines changed

7 files changed

+29
-30
lines changed

Include/ceval.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void);
3838
PyAPI_FUNC(PyObject *) PyEval_GetLocals(void);
3939
PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void);
4040

41+
#ifndef Py_LIMITED_API
42+
/* Helper to look up a builtin object */
43+
PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *);
4144
/* Look at the current frame's (if any) code's co_flags, and turn on
4245
the corresponding compiler flags in cf->cf_flags. Return 1 if any
4346
flag was set, else return 0. */
44-
#ifndef Py_LIMITED_API
4547
PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf);
4648
#endif
4749

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed error handling in pickling methods when fail to look up builtin
2+
"getattr".

Modules/_pickle.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,19 +200,15 @@ _Pickle_ClearState(PickleState *st)
200200
static int
201201
_Pickle_InitState(PickleState *st)
202202
{
203-
PyObject *builtins;
204203
PyObject *copyreg = NULL;
205204
PyObject *compat_pickle = NULL;
206205
PyObject *codecs = NULL;
207206
PyObject *functools = NULL;
207+
_Py_IDENTIFIER(getattr);
208208

209-
builtins = PyEval_GetBuiltins();
210-
if (builtins == NULL)
211-
goto error;
212-
st->getattr = PyDict_GetItemString(builtins, "getattr");
209+
st->getattr = _PyEval_GetBuiltinId(&PyId_getattr);
213210
if (st->getattr == NULL)
214211
goto error;
215-
Py_INCREF(st->getattr);
216212

217213
copyreg = PyImport_ImportModule("copyreg");
218214
if (!copyreg)

Objects/classobject.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,15 @@ method_reduce(PyMethodObject *im)
7575
{
7676
PyObject *self = PyMethod_GET_SELF(im);
7777
PyObject *func = PyMethod_GET_FUNCTION(im);
78-
PyObject *builtins;
79-
PyObject *getattr;
8078
PyObject *funcname;
8179
_Py_IDENTIFIER(getattr);
8280

8381
funcname = _PyObject_GetAttrId(func, &PyId___name__);
8482
if (funcname == NULL) {
8583
return NULL;
8684
}
87-
builtins = PyEval_GetBuiltins();
88-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
89-
return Py_BuildValue("O(ON)", getattr, self, funcname);
85+
return Py_BuildValue("N(ON)", _PyEval_GetBuiltinId(&PyId_getattr),
86+
self, funcname);
9087
}
9188

9289
static PyMethodDef method_methods[] = {

Objects/descrobject.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -389,14 +389,9 @@ descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
389389
static PyObject *
390390
descr_reduce(PyDescrObject *descr)
391391
{
392-
PyObject *builtins;
393-
PyObject *getattr;
394392
_Py_IDENTIFIER(getattr);
395-
396-
builtins = PyEval_GetBuiltins();
397-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
398-
return Py_BuildValue("O(OO)", getattr, PyDescr_TYPE(descr),
399-
PyDescr_NAME(descr));
393+
return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
394+
PyDescr_TYPE(descr), PyDescr_NAME(descr));
400395
}
401396

402397
static PyMethodDef descr_methods[] = {
@@ -1098,13 +1093,9 @@ wrapper_repr(wrapperobject *wp)
10981093
static PyObject *
10991094
wrapper_reduce(wrapperobject *wp)
11001095
{
1101-
PyObject *builtins;
1102-
PyObject *getattr;
11031096
_Py_IDENTIFIER(getattr);
1104-
1105-
builtins = PyEval_GetBuiltins();
1106-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
1107-
return Py_BuildValue("O(OO)", getattr, wp->self, PyDescr_NAME(wp->descr));
1097+
return Py_BuildValue("N(OO)", _PyEval_GetBuiltinId(&PyId_getattr),
1098+
wp->self, PyDescr_NAME(wp->descr));
11081099
}
11091100

11101101
static PyMethodDef wrapper_methods[] = {

Objects/methodobject.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,16 +320,13 @@ meth_dealloc(PyCFunctionObject *m)
320320
static PyObject *
321321
meth_reduce(PyCFunctionObject *m)
322322
{
323-
PyObject *builtins;
324-
PyObject *getattr;
325323
_Py_IDENTIFIER(getattr);
326324

327325
if (m->m_self == NULL || PyModule_Check(m->m_self))
328326
return PyUnicode_FromString(m->m_ml->ml_name);
329327

330-
builtins = PyEval_GetBuiltins();
331-
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
332-
return Py_BuildValue("O(Os)", getattr, m->m_self, m->m_ml->ml_name);
328+
return Py_BuildValue("N(Os)", _PyEval_GetBuiltinId(&PyId_getattr),
329+
m->m_self, m->m_ml->ml_name);
333330
}
334331

335332
static PyMethodDef meth_methods[] = {

Python/ceval.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4667,6 +4667,20 @@ PyEval_GetBuiltins(void)
46674667
return current_frame->f_builtins;
46684668
}
46694669

4670+
/* Convenience function to get a builtin from its name */
4671+
PyObject *
4672+
_PyEval_GetBuiltinId(_Py_Identifier *name)
4673+
{
4674+
PyObject *attr = _PyDict_GetItemIdWithError(PyEval_GetBuiltins(), name);
4675+
if (attr) {
4676+
Py_INCREF(attr);
4677+
}
4678+
else if (!PyErr_Occurred()) {
4679+
PyErr_SetObject(PyExc_AttributeError, _PyUnicode_FromId(name));
4680+
}
4681+
return attr;
4682+
}
4683+
46704684
PyObject *
46714685
PyEval_GetLocals(void)
46724686
{

0 commit comments

Comments
 (0)