From 017bd0a6bbe6d3c5d404c265bf4700ec7abffa20 Mon Sep 17 00:00:00 2001 From: Kjetil Matheussen Date: Sat, 16 Jul 2016 14:43:32 +0200 Subject: [PATCH] Handle load_segs overflow in register_dynlib_callback gracefully * dyn_load.c [HAVE_DL_ITERATE_PHDR and PT_GNU_RELRO] (GC_register_dynlib_callback): If n_load_segs reaches MAX_LOAD_SEGS then call WARN (with the appropriate message) and call GC_add_roots_inner to register the segment directly instead of ABORT. --- dyn_load.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dyn_load.c b/dyn_load.c index c0f9c5b3..3d6b98bd 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -527,7 +527,6 @@ STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info, if (callback != 0 && !callback(info->dlpi_name, start, p->p_memsz)) break; # ifdef PT_GNU_RELRO - if (n_load_segs >= MAX_LOAD_SEGS) ABORT("Too many PT_LOAD segs"); # if CPP_WORDSZ == 64 /* FIXME: GC_push_all eventually does the correct */ /* rounding to the next multiple of ALIGNMENT, so, most */ @@ -536,11 +535,17 @@ STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info, /* start pointer value may require aligning */ start = (ptr_t)((word)start & ~(sizeof(word) - 1)); # endif - load_segs[n_load_segs].start = start; - load_segs[n_load_segs].end = end; - load_segs[n_load_segs].start2 = 0; - load_segs[n_load_segs].end2 = 0; - ++n_load_segs; + if (n_load_segs >= MAX_LOAD_SEGS) { + WARN("Too many PT_LOAD segments;" + " registering as roots directly...\n", 0); + GC_add_roots_inner(start, end, TRUE); + } else { + load_segs[n_load_segs].start = start; + load_segs[n_load_segs].end = end; + load_segs[n_load_segs].start2 = 0; + load_segs[n_load_segs].end2 = 0; + ++n_load_segs; + } # else GC_add_roots_inner(start, end, TRUE); # endif /* PT_GNU_RELRO */ -- 2.50.1