Skip to content

Commit a3648df

Browse files
committed
gh-130030: Fix crash on 32-bit Linux with free threading
The `gc_get_refs` assertion needs to be after we check the alive and unreachable bits. Otherwise, `ob_tid` may store the actual thread id instead of the computed `gc_refs`, which may trigger the assertion if the `ob_tid` looks like a negative value. Also fix a few type warnings on 32-bit systems.
1 parent 3e222e3 commit a3648df

File tree

2 files changed

+13
-13
lines changed

2 files changed

+13
-13
lines changed

Objects/obmalloc.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3297,12 +3297,12 @@ static bool _collect_alloc_stats(
32973297
static void
32983298
py_mimalloc_print_stats(FILE *out)
32993299
{
3300-
fprintf(out, "Small block threshold = %zd, in %u size classes.\n",
3301-
MI_SMALL_OBJ_SIZE_MAX, MI_BIN_HUGE);
3302-
fprintf(out, "Medium block threshold = %zd\n",
3303-
MI_MEDIUM_OBJ_SIZE_MAX);
3304-
fprintf(out, "Large object max size = %zd\n",
3305-
MI_LARGE_OBJ_SIZE_MAX);
3300+
fprintf(out, "Small block threshold = %zu, in %u size classes.\n",
3301+
(size_t)MI_SMALL_OBJ_SIZE_MAX, MI_BIN_HUGE);
3302+
fprintf(out, "Medium block threshold = %zu\n",
3303+
(size_t)MI_MEDIUM_OBJ_SIZE_MAX);
3304+
fprintf(out, "Large object max size = %zu\n",
3305+
(size_t)MI_LARGE_OBJ_SIZE_MAX);
33063306

33073307
mi_heap_t *heap = mi_heap_get_default();
33083308
struct _alloc_stats stats;

Python/gc_free_threading.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -564,8 +564,8 @@ typedef struct {
564564
} gc_span_stack_t;
565565

566566
typedef struct {
567-
unsigned int in;
568-
unsigned int out;
567+
Py_ssize_t in;
568+
Py_ssize_t out;
569569
_PyObjectStack stack;
570570
gc_span_stack_t spans;
571571
PyObject *buffer[BUFFER_SIZE];
@@ -574,14 +574,14 @@ typedef struct {
574574

575575

576576
// Returns number of entries in buffer
577-
static inline unsigned int
577+
static inline Py_ssize_t
578578
gc_mark_buffer_len(gc_mark_args_t *args)
579579
{
580580
return args->in - args->out;
581581
}
582582

583583
// Returns number of free entry slots in buffer
584-
static inline unsigned int
584+
static inline Py_ssize_t
585585
gc_mark_buffer_avail(gc_mark_args_t *args)
586586
{
587587
return BUFFER_SIZE - gc_mark_buffer_len(args);
@@ -1074,14 +1074,14 @@ mark_heap_visitor(const mi_heap_t *heap, const mi_heap_area_t *area,
10741074
return true;
10751075
}
10761076

1077-
_PyObject_ASSERT_WITH_MSG(op, gc_get_refs(op) >= 0,
1078-
"refcount is too small");
1079-
10801077
if (gc_is_alive(op) || !gc_is_unreachable(op)) {
10811078
// Object was already marked as reachable.
10821079
return true;
10831080
}
10841081

1082+
_PyObject_ASSERT_WITH_MSG(op, gc_get_refs(op) >= 0,
1083+
"refcount is too small");
1084+
10851085
// GH-129236: If we've seen an active frame without a valid stack pointer,
10861086
// then we can't collect objects with deferred references because we may
10871087
// have missed some reference to the object on the stack. In that case,

0 commit comments

Comments
 (0)