Skip to content

Commit 22ca169

Browse files
committed
Use uintptr_t instead of char * to avoid warnings and UB
1 parent afeb866 commit 22ca169

File tree

5 files changed

+25
-19
lines changed

5 files changed

+25
-19
lines changed

Include/cpython/pystate.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,9 @@ struct _ts {
112112
int py_recursion_remaining;
113113
int py_recursion_limit;
114114

115-
char *c_stack_soft_limit;
116-
char *c_stack_hard_limit;
115+
// These are addresses, but we need to convert to ints to avoid UB.
116+
uintptr_t c_stack_soft_limit;
117+
uintptr_t c_stack_hard_limit;
117118
int recursion_headroom; /* Allow 50 more calls to handle any errors. */
118119

119120
/* 'tracing' keeps track of the execution depth when tracing/profiling.

Include/internal/pycore_ceval.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ extern void _PyEval_DeactivateOpCache(void);
195195

196196
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
197197
char here;
198-
return &here < tstate->c_stack_soft_limit;
198+
uintptr_t here_addr = (uintptr_t)&here;
199+
return here_addr < tstate->c_stack_soft_limit;
199200
}
200201

201202
// Export for '_json' shared extension, used via _Py_EnterRecursiveCall()
@@ -223,7 +224,8 @@ static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) {
223224

224225
static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate, int margin_count) {
225226
char here;
226-
return &here <= tstate->c_stack_soft_limit + margin_count * PYOS_STACK_MARGIN_BYTES;
227+
uintptr_t here_addr = (uintptr_t)&here;
228+
return here_addr <= tstate->c_stack_soft_limit + margin_count * PYOS_STACK_MARGIN_BYTES;
227229
}
228230

229231
static inline void _Py_LeaveRecursiveCall(void) {

Modules/_testinternalcapi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ get_c_recursion_remaining(PyObject *self, PyObject *Py_UNUSED(args))
116116
{
117117
PyThreadState *tstate = _PyThreadState_GET();
118118
char here;
119-
int remaining = (int)((&here - tstate->c_stack_soft_limit)/PYOS_STACK_MARGIN_BYTES * 50);
119+
uintptr_t here_addr = (uintptr_t)&here;
120+
int remaining = (int)((here_addr - tstate->c_stack_soft_limit)/PYOS_STACK_MARGIN_BYTES * 50);
120121
return PyLong_FromLong(remaining);
121122
}
122123

Python/ceval.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,8 @@ void
312312
_Py_EnterRecursiveCallUnchecked(PyThreadState *tstate)
313313
{
314314
char here;
315-
if (&here < tstate->c_stack_hard_limit) {
315+
uintptr_t here_addr = (uintptr_t)&here;
316+
if (here_addr < tstate->c_stack_hard_limit) {
316317
Py_FatalError("Unchecked stack overflow.");
317318
}
318319
}
@@ -329,29 +330,30 @@ int
329330
_Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
330331
{
331332
char here;
332-
assert(tstate->c_stack_soft_limit != NULL);
333-
if (tstate->c_stack_hard_limit == NULL) {
333+
uintptr_t here_addr = (uintptr_t)&here;
334+
assert(tstate->c_stack_soft_limit != 0);
335+
if (tstate->c_stack_hard_limit == 0) {
334336
#ifdef USE_STACKCHECK
335337
assert(_PyOS_CheckStack(PYOS_STACK_MARGIN));
336338
if (_PyOS_CheckStack(PYOS_STACK_MARGIN * 2) == 0) {
337-
tstate->c_stack_soft_limit = &here - PYOS_STACK_MARGIN_BYTES;
339+
tstate->c_stack_soft_limit = here_addr - PYOS_STACK_MARGIN_BYTES;
338340
return 0;
339341
}
340342
else {
341-
assert(tstate->c_stack_soft_limit != (char*)UINTPTR_MAX);
343+
assert(tstate->c_stack_soft_limit != UINTPTR_MAX);
342344
tstate->c_stack_hard_limit = tstate->c_stack_soft_limit - PYOS_STACK_MARGIN_BYTES;
343-
}F
345+
}
344346
#else
345-
assert(tstate->c_stack_soft_limit == (char*)UINTPTR_MAX);
346-
tstate->c_stack_soft_limit = &here - Py_C_STACK_SIZE;
347-
tstate->c_stack_hard_limit = &here - (Py_C_STACK_SIZE + PYOS_STACK_MARGIN_BYTES);
347+
assert(tstate->c_stack_soft_limit == UINTPTR_MAX);
348+
tstate->c_stack_soft_limit = here_addr - Py_C_STACK_SIZE;
349+
tstate->c_stack_hard_limit = here_addr - (Py_C_STACK_SIZE + PYOS_STACK_MARGIN_BYTES);
348350
#endif
349351
}
350-
if (&here >= tstate->c_stack_soft_limit) {
352+
if (here_addr >= tstate->c_stack_soft_limit) {
351353
return 0;
352354
}
353-
assert(tstate->c_stack_hard_limit != NULL);
354-
if (&here < tstate->c_stack_hard_limit) {
355+
assert(tstate->c_stack_hard_limit != 0);
356+
if (here_addr < tstate->c_stack_hard_limit) {
355357
/* Overflowing while handling an overflow. Give up. */
356358
Py_FatalError("Cannot recover from stack overflow.");
357359
}

Python/pystate.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,8 +1492,8 @@ init_threadstate(_PyThreadStateImpl *_tstate,
14921492

14931493
tstate->py_recursion_limit = interp->ceval.recursion_limit;
14941494
tstate->py_recursion_remaining = interp->ceval.recursion_limit;
1495-
tstate->c_stack_soft_limit = (char *)UINTPTR_MAX;
1496-
tstate->c_stack_hard_limit = NULL;
1495+
tstate->c_stack_soft_limit = UINTPTR_MAX;
1496+
tstate->c_stack_hard_limit = 0;
14971497

14981498
tstate->exc_info = &tstate->exc_state;
14991499

0 commit comments

Comments
 (0)