Skip to content

Commit d1453f6

Browse files
authored
GH-121459: Streamline PyObject* to PyStackRef conversions by disallowing NULL pointers. (GH-124894)
1 parent 10094a5 commit d1453f6

File tree

4 files changed

+63
-57
lines changed

4 files changed

+63
-57
lines changed

Include/internal/pycore_stackref.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ PyStackRef_AsPyObjectBorrow(_PyStackRef stackref)
111111
static inline PyObject *
112112
PyStackRef_AsPyObjectSteal(_PyStackRef stackref)
113113
{
114-
if (!PyStackRef_IsNull(stackref) && PyStackRef_IsDeferred(stackref)) {
114+
assert(!PyStackRef_IsNull(stackref));
115+
if (PyStackRef_IsDeferred(stackref)) {
115116
return Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref));
116117
}
117118
return PyStackRef_AsPyObjectBorrow(stackref);
@@ -131,9 +132,10 @@ PyStackRef_AsPyObjectSteal(_PyStackRef stackref)
131132
static inline _PyStackRef
132133
_PyStackRef_FromPyObjectSteal(PyObject *obj)
133134
{
135+
assert(obj != NULL);
134136
// Make sure we don't take an already tagged value.
135137
assert(((uintptr_t)obj & Py_TAG_BITS) == 0);
136-
unsigned int tag = (obj == NULL || _Py_IsImmortal(obj)) ? (Py_TAG_DEFERRED) : Py_TAG_PTR;
138+
unsigned int tag = _Py_IsImmortal(obj) ? (Py_TAG_DEFERRED) : Py_TAG_PTR;
137139
return ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag});
138140
}
139141
# define PyStackRef_FromPyObjectSteal(obj) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj))
@@ -193,6 +195,7 @@ PyStackRef_FromPyObjectImmortal(PyObject *obj)
193195
# define PyStackRef_CLOSE(REF) \
194196
do { \
195197
_PyStackRef _close_tmp = (REF); \
198+
assert(!PyStackRef_IsNull(_close_tmp)); \
196199
if (!PyStackRef_IsDeferred(_close_tmp)) { \
197200
Py_DECREF(PyStackRef_AsPyObjectBorrow(_close_tmp)); \
198201
} \
@@ -214,10 +217,11 @@ PyStackRef_FromPyObjectImmortal(PyObject *obj)
214217
static inline _PyStackRef
215218
PyStackRef_DUP(_PyStackRef stackref)
216219
{
220+
assert(!PyStackRef_IsNull(stackref));
217221
if (PyStackRef_IsDeferred(stackref)) {
218-
assert(PyStackRef_IsNull(stackref) ||
219-
_Py_IsImmortal(PyStackRef_AsPyObjectBorrow(stackref)) ||
220-
_PyObject_HasDeferredRefcount(PyStackRef_AsPyObjectBorrow(stackref)));
222+
assert(_Py_IsImmortal(PyStackRef_AsPyObjectBorrow(stackref)) ||
223+
_PyObject_HasDeferredRefcount(PyStackRef_AsPyObjectBorrow(stackref))
224+
);
221225
return stackref;
222226
}
223227
Py_INCREF(PyStackRef_AsPyObjectBorrow(stackref));

Python/bytecodes.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,9 +1922,10 @@ dummy_func(
19221922
DECREF_INPUTS();
19231923
ERROR_IF(super == NULL, error);
19241924
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
1925-
attr = PyStackRef_FromPyObjectSteal(PyObject_GetAttr(super, name));
1925+
PyObject *attr_o = PyObject_GetAttr(super, name);
19261926
Py_DECREF(super);
1927-
ERROR_IF(PyStackRef_IsNull(attr), error);
1927+
ERROR_IF(attr_o == NULL, error);
1928+
attr = PyStackRef_FromPyObjectSteal(attr_o);
19281929
null = PyStackRef_NULL;
19291930
}
19301931

@@ -2740,9 +2741,10 @@ dummy_func(
27402741

27412742
inst(GET_ITER, (iterable -- iter)) {
27422743
/* before: [obj]; after [getiter(obj)] */
2743-
iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)));
2744+
PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable));
27442745
DECREF_INPUTS();
2745-
ERROR_IF(PyStackRef_IsNull(iter), error);
2746+
ERROR_IF(iter_o == NULL, error);
2747+
iter = PyStackRef_FromPyObjectSteal(iter_o);
27462748
}
27472749

27482750
inst(GET_YIELD_FROM_ITER, (iterable -- iter)) {
@@ -3052,16 +3054,18 @@ dummy_func(
30523054
PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner);
30533055
PyObject *name = _Py_SpecialMethods[oparg].name;
30543056
PyObject *self_or_null_o;
3055-
attr = PyStackRef_FromPyObjectSteal(_PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o));
3056-
if (PyStackRef_IsNull(attr)) {
3057+
PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o);
3058+
if (attr_o == NULL) {
30573059
if (!_PyErr_Occurred(tstate)) {
30583060
_PyErr_Format(tstate, PyExc_TypeError,
30593061
_Py_SpecialMethods[oparg].error,
30603062
Py_TYPE(owner_o)->tp_name);
30613063
}
3064+
ERROR_IF(true, error);
30623065
}
3063-
ERROR_IF(PyStackRef_IsNull(attr), error);
3064-
self_or_null = PyStackRef_FromPyObjectSteal(self_or_null_o);
3066+
attr = PyStackRef_FromPyObjectSteal(attr_o);
3067+
self_or_null = self_or_null_o == NULL ?
3068+
PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o);
30653069
}
30663070

30673071
inst(WITH_EXCEPT_START, (exit_func, exit_self, lasti, unused, val -- exit_func, exit_self, lasti, unused, val, res)) {
@@ -3092,9 +3096,10 @@ dummy_func(
30923096
(void)lasti; // Shut up compiler warning if asserts are off
30933097
PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb};
30943098
int has_self = !PyStackRef_IsNull(exit_self);
3095-
res = PyStackRef_FromPyObjectSteal(PyObject_Vectorcall(exit_func_o, stack + 2 - has_self,
3096-
(3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL));
3097-
ERROR_IF(PyStackRef_IsNull(res), error);
3099+
PyObject *res_o = PyObject_Vectorcall(exit_func_o, stack + 2 - has_self,
3100+
(3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
3101+
ERROR_IF(res_o == NULL, error);
3102+
res = PyStackRef_FromPyObjectSteal(res_o);
30983103
}
30993104

31003105
pseudo(SETUP_FINALLY, (-- unused), (HAS_ARG)) = {
@@ -4539,9 +4544,10 @@ dummy_func(
45394544
/* If value is a unicode object, then we know the result
45404545
* of format(value) is value itself. */
45414546
if (!PyUnicode_CheckExact(value_o)) {
4542-
res = PyStackRef_FromPyObjectSteal(PyObject_Format(value_o, NULL));
4547+
PyObject *res_o = PyObject_Format(value_o, NULL);
45434548
PyStackRef_CLOSE(value);
4544-
ERROR_IF(PyStackRef_IsNull(res), error);
4549+
ERROR_IF(res_o == NULL, error);
4550+
res = PyStackRef_FromPyObjectSteal(res_o);
45454551
}
45464552
else {
45474553
res = value;

Python/executor_cases.c.h

Lines changed: 16 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 19 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)