Skip to content

Commit 1775754

Browse files
committed
PyUnstable_ThreadState_SetStack() can fail
1 parent ba0d3ed commit 1775754

File tree

4 files changed

+29
-9
lines changed

4 files changed

+29
-9
lines changed

Doc/c-api/init.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1353,12 +1353,15 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
13531353
.. versionadded:: 3.11
13541354
13551355
1356-
.. c:function:: void PyUnstable_ThreadState_SetStack(PyThreadState *tstate, void *stack_start_addr, size_t stack_size)
1356+
.. c:function:: int PyUnstable_ThreadState_SetStack(PyThreadState *tstate, void *stack_start_addr, size_t stack_size)
13571357
13581358
Set the stack start address and stack size of a Python thread state.
13591359
13601360
*stack_size* must be greater than ``0``.
13611361
1362+
On success, return ``0``.
1363+
On failure, set an exception and return ``-1``.
1364+
13621365
.. seealso::
13631366
The :c:func:`PyUnstable_ThreadState_ResetStack` function.
13641367

Include/cpython/pystate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ PyAPI_FUNC(int) PyGILState_Check(void);
253253
PyAPI_FUNC(PyObject*) _PyThread_CurrentFrames(void);
254254

255255
// Set the stack start address and stack size of a Python thread state
256-
PyAPI_FUNC(void) PyUnstable_ThreadState_SetStack(
256+
PyAPI_FUNC(int) PyUnstable_ThreadState_SetStack(
257257
PyThreadState *tstate,
258258
void *stack_start_addr, // Stack start address
259259
size_t stack_size); // Stack size (in bytes)

Modules/_testinternalcapi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2421,7 +2421,8 @@ set_vectorcall_nop(PyObject *self, PyObject *func)
24212421
static void
24222422
check_threadstate_set_stack(PyThreadState *tstate, void *start, size_t size)
24232423
{
2424-
PyUnstable_ThreadState_SetStack(tstate, start, size);
2424+
assert(PyUnstable_ThreadState_SetStack(tstate, start, size) == 0);
2425+
assert(!PyErr_Occurred());
24252426

24262427
_PyThreadStateImpl *ts = (_PyThreadStateImpl *)tstate;
24272428
assert(ts->c_stack_hard_limit == (uintptr_t)start);
@@ -2435,6 +2436,7 @@ static PyObject *
24352436
test_threadstate_set_stack(PyObject *self, PyObject *Py_UNUSED(args))
24362437
{
24372438
PyThreadState *tstate = PyThreadState_GET();
2439+
assert(!PyErr_Occurred());
24382440

24392441
// Test a size smaller than _PyOS_STACK_MARGIN_BYTES
24402442
size_t size = 4096;

Python/ceval.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,8 @@ int pthread_attr_destroy(pthread_attr_t *a)
440440

441441

442442
void
443-
PyUnstable_ThreadState_SetStack(PyThreadState *tstate,
444-
void *stack_start_addr, size_t stack_size)
443+
tstate_set_stack(PyThreadState *tstate,
444+
void *stack_start_addr, size_t stack_size)
445445
{
446446
assert(stack_size > 0);
447447

@@ -473,6 +473,21 @@ PyUnstable_ThreadState_SetStack(PyThreadState *tstate,
473473
}
474474

475475

476+
int
477+
PyUnstable_ThreadState_SetStack(PyThreadState *tstate,
478+
void *stack_start_addr, size_t stack_size)
479+
{
480+
if (stack_size == 0) {
481+
PyErr_SetString(PyExc_ValueError, "stack_size must be greater than 0");
482+
return -1;
483+
}
484+
485+
tstate_set_stack(tstate, stack_start_addr, stack_size);
486+
return 0;
487+
}
488+
489+
490+
476491
void
477492
PyUnstable_ThreadState_ResetStack(PyThreadState *tstate)
478493
{
@@ -485,13 +500,13 @@ PyUnstable_ThreadState_ResetStack(PyThreadState *tstate)
485500

486501
uintptr_t start = (uintptr_t)low + guarantee + _PyOS_STACK_MARGIN_BYTES;
487502
size_t size = (uintptr_t)high - start;
488-
PyUnstable_ThreadState_SetStack(tstate, (void*)start, size);
503+
tstate_set_stack(tstate, (void*)start, size);
489504

490505
#elif defined(__APPLE__)
491506
pthread_t this_thread = pthread_self();
492507
void *top = pthread_get_stackaddr_np(this_thread); // top of the stack
493508
size_t size = pthread_get_stacksize_np(this_thread);
494-
PyUnstable_ThreadState_SetStack(tstate, (char*)top - size, size);
509+
tstate_set_stack(tstate, (char*)top - size, size);
495510

496511
#else
497512
// XXX musl supports HAVE_PTHRED_GETATTR_NP, but the resulting stack size
@@ -512,7 +527,7 @@ PyUnstable_ThreadState_ResetStack(PyThreadState *tstate)
512527
uintptr_t base = ((uintptr_t)stack_addr) + guard_size;
513528
uintptr_t start = base + _PyOS_STACK_MARGIN_BYTES;
514529
size_t pystack_size = (base + stack_size) - start;
515-
PyUnstable_ThreadState_SetStack(tstate, (void*)start, pystack_size);
530+
tstate_set_stack(tstate, (void*)start, pystack_size);
516531
}
517532
else
518533
# endif
@@ -521,7 +536,7 @@ PyUnstable_ThreadState_ResetStack(PyThreadState *tstate)
521536
uintptr_t top = _Py_SIZE_ROUND_UP(here_addr, 4096);
522537
uintptr_t start = top - (Py_C_STACK_SIZE + _PyOS_STACK_MARGIN_BYTES);
523538
size_t pystack_size = top - start;
524-
PyUnstable_ThreadState_SetStack(tstate, (void*)start, pystack_size);
539+
tstate_set_stack(tstate, (void*)start, pystack_size);
525540
}
526541
#endif
527542
}

0 commit comments

Comments
 (0)