]> granicus.if.org Git - gc/commitdiff
Handle load_segs overflow in register_dynlib_callback gracefully
authorKjetil Matheussen <k.s.matheussen@notam02.no>
Sat, 16 Jul 2016 12:43:32 +0000 (14:43 +0200)
committerIvan Maidanski <ivmai@mail.ru>
Thu, 10 Nov 2016 18:02:52 +0000 (21:02 +0300)
* 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

index a4d25a60eb0fd573a3225a858233791a3edef24b..b50a6473cd8612bde1714ffe98bbd0b6b85992cc 100644 (file)
@@ -486,7 +486,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   */
@@ -495,11 +494,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 */