diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2023-05-13 11:41:19 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2023-05-13 11:41:19 +0300 |
commit | 1c2d6cf5439a052e06369c36746d3c1f07900e22 (patch) | |
tree | 33450802ad3a87e8abed0bd7ca93c4c303076024 | |
parent | a0a416a8a9c5ad98678207ef8fa3a9b8e1262318 (diff) | |
download | bdwgc-1c2d6cf5439a052e06369c36746d3c1f07900e22.tar.gz |
Fix comparisons to heap boundary in GC_get_back_ptr_info and GC_mark_from
The region delimited by GC_least_plausible_heap_addr and
GC_greatest_plausible_heap_addr might contain part of static data
roots or stacks (in addition to potential heap expansion areas).
Certain comparisons in GC_get_back_ptr_info (when ALIGNMENT is 1) and
in GC_mark_from (in assertions) expect the real heap boundaries.
* alloc.c [SET_REAL_HEAP_BOUNDS] (GC_add_to_heap): Update
GC_least_real_heap_addr and GC_greatest_real_heap_addr variables.
* dbg_mlc.c [KEEP_BACK_PTRS && ALIGNMENT == 1] (GC_get_back_ptr_info):
Compare alternate_target and target to GC_least_real_heap_addr
and GC_greatest_real_heap_addr (instead of GC_least_plausible_heap_addr
and GC_greatest_plausible_heap_addr).
* include/gc/gc_mark.h (GC_greatest_plausible_heap_addr): Refine
comment.
* include/private/gc_priv.h [GC_ASSERTIONS || KEEP_BACK_PTRS
&& ALIGNMENT == 1] (SET_REAL_HEAP_BOUNDS): Define macro.
* include/private/gc_priv.h [GC_ASSERTIONS || KEEP_BACK_PTRS
&& ALIGNMENT == 1] (GC_least_real_heap_addr,
GC_greatest_real_heap_addr): Define (as macro).
* include/private/gc_priv.h [GC_ASSERTIONS || KEEP_BACK_PTRS
&& ALIGNMENT == 1] (_GC_arrays._least_real_heap_addr,
_GC_arrays._greatest_real_heap_addr): New field; add comment.
* mark.c (GC_mark_from): Use GC_greatest_real_heap_addr and
GC_least_real_heap_addr instead of GC_least_plausible_heap_addr and
GC_greatest_plausible_heap_addr, respectively, in assertions.
-rw-r--r-- | alloc.c | 8 | ||||
-rw-r--r-- | dbg_mlc.c | 8 | ||||
-rw-r--r-- | include/gc/gc_mark.h | 4 | ||||
-rw-r--r-- | include/private/gc_priv.h | 10 | ||||
-rw-r--r-- | mark.c | 19 |
5 files changed, 32 insertions, 17 deletions
@@ -1434,7 +1434,13 @@ STATIC void GC_add_to_heap(struct hblk *p, size_t bytes) if (endp > (word)GC_greatest_plausible_heap_addr) { GC_greatest_plausible_heap_addr = (void *)endp; } - +# ifdef SET_REAL_HEAP_BOUNDS + if ((word)p < GC_least_real_heap_addr + || EXPECT(0 == GC_least_real_heap_addr, FALSE)) + GC_least_real_heap_addr = (word)p - sizeof(word); + if (endp > GC_greatest_real_heap_addr) + GC_greatest_real_heap_addr = endp; +# endif if (EXPECT(old_capacity > 0, FALSE)) { # ifndef GWW_VDB /* Recycling may call GC_add_to_heap() again but should not */ @@ -133,10 +133,10 @@ ptr_t target = *(ptr_t *)bp; ptr_t alternate_target = *(ptr_t *)alternate_ptr; - if ((word)alternate_target >= (word)GC_least_plausible_heap_addr - && (word)alternate_target < (word)GC_greatest_plausible_heap_addr - && ((word)target < (word)GC_least_plausible_heap_addr - || (word)target >= (word)GC_greatest_plausible_heap_addr)) { + if ((word)alternate_target > GC_least_real_heap_addr + && (word)alternate_target < GC_greatest_real_heap_addr + && ((word)target <= GC_least_real_heap_addr + || (word)target >= GC_greatest_real_heap_addr)) { bp = alternate_ptr; } } diff --git a/include/gc/gc_mark.h b/include/gc/gc_mark.h index 6142e750..acec052b 100644 --- a/include/gc/gc_mark.h +++ b/include/gc/gc_mark.h @@ -128,7 +128,9 @@ GC_API void * GC_greatest_plausible_heap_addr; /* Bounds on the heap. Guaranteed to be valid. */ /* Likely to include future heap expansion. */ /* Hence usually includes not-yet-mapped */ - /* memory. The address of any heap object is */ + /* memory, or might overlap with other data */ + /* roots. The address of any heap object is */ + /* larger than GC_least_plausible_heap_addr and */ /* less than GC_greatest_plausible_heap_addr. */ /* Handle nested references in a custom mark procedure. */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 8091b7f3..84bcc14c 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1448,6 +1448,16 @@ struct _GC_arrays { /* obtained scratch area. */ /* Used by GC_register_dynamic_libraries(). */ # endif +# if defined(GC_ASSERTIONS) || (defined(KEEP_BACK_PTRS) && ALIGNMENT == 1) +# define SET_REAL_HEAP_BOUNDS +# define GC_least_real_heap_addr GC_arrays._least_real_heap_addr +# define GC_greatest_real_heap_addr GC_arrays._greatest_real_heap_addr + word _least_real_heap_addr; + word _greatest_real_heap_addr; + /* Similar to GC_least/greatest_plausible_heap_addr but */ + /* do not include future (potential) heap expansion. */ + /* Both variables are zero initially. */ +# endif mse *_mark_stack; /* Limits of stack for GC_mark routine. All ranges */ /* between GC_mark_stack (incl.) and GC_mark_stack_top */ @@ -618,11 +618,10 @@ GC_INNER mse * GC_mark_from(mse *mark_stack_top, mse *mark_stack, /* too much on the stack. */ /* Either it is a heap object or a region outside the heap. */ - GC_ASSERT(descr <= (word)GC_greatest_plausible_heap_addr - - (word)GC_least_plausible_heap_addr - || (word)(current_p + descr) - <= (word)GC_least_plausible_heap_addr - || (word)current_p >= (word)GC_greatest_plausible_heap_addr); + GC_ASSERT(descr < GC_greatest_real_heap_addr-GC_least_real_heap_addr + || (word)current_p + descr + <= GC_least_real_heap_addr + sizeof(word) + || (word)current_p >= GC_greatest_real_heap_addr); # ifdef PARALLEL_MARK # define SHARE_BYTES 2048 if (descr > SHARE_BYTES && GC_parallel @@ -930,12 +929,10 @@ STATIC mse * GC_steal_mark_stack(mse * low, mse * high, mse * local, top -> mse_descr.w = descr; top -> mse_start = p -> mse_start; GC_ASSERT((descr & GC_DS_TAGS) != GC_DS_LENGTH /* 0 */ - || descr <= (word)GC_greatest_plausible_heap_addr - - (word)GC_least_plausible_heap_addr - || (word)(p -> mse_start + descr) - <= (word)GC_least_plausible_heap_addr - || (word)p -> mse_start - >= (word)GC_greatest_plausible_heap_addr); + || descr < GC_greatest_real_heap_addr-GC_least_real_heap_addr + || (word)(p -> mse_start + descr) + <= GC_least_real_heap_addr + sizeof(word) + || (word)(p -> mse_start) >= GC_greatest_real_heap_addr); /* If this is a big object, count it as size/256 + 1 objects. */ ++i; if ((descr & GC_DS_TAGS) == GC_DS_LENGTH) i += (int)(descr >> 8); |