From b1d1b5e1f8fbcb2e7016c8a4d2e7fc45975504e3 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Sep 2016 23:37:43 -0400 Subject: [PATCH] Fix bugs with memory allocation in ego. cf/cf_loop.c and share/put.c tried to read the next pointer in an element of a linked list after freeing the element. ud/ud_copy.c tried to read beyond the end of the _defs_ array: it only has _nrexpldefs_ elements, not _nrdefs_ elements. These bugs caused core dumps on OpenBSD. Its malloc() put _defs_ near the end of a page, so reading beyond the end crossed into an unmapped page. Its free() wrote junk bytes and changed the next pointer to 0xdfdfdfdfdfdfdfdf. --- util/ego/cf/cf_loop.c | 7 +++++-- util/ego/share/put.c | 5 ++++- util/ego/ud/ud_copy.c | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/util/ego/cf/cf_loop.c b/util/ego/cf/cf_loop.c index c14bdba3f..b3b2d5c70 100644 --- a/util/ego/cf/cf_loop.c +++ b/util/ego/cf/cf_loop.c @@ -171,9 +171,12 @@ STATIC collapse_loops(loops_p) for (li1 = Lfirst(*loops_p); li1 != (Lindex) 0; li1 = Lnext(li1,*loops_p)) { lp1 = (loop_p) Lelem(li1); lp1->lp_level = (short) 0; - for (li2 = Lfirst(*loops_p); li2 != (Lindex) 0; - li2 = Lnext(li2,*loops_p)) { + /* Lnext(li2,*loops_p) must happen before + * Lremove(lp2,loops_p) releases the memory for li2. + */ + for (li2 = Lfirst(*loops_p); li2 != (Lindex) 0;) { lp2 = (loop_p) Lelem(li2); + li2 = Lnext(li2,*loops_p); if (lp1 != lp2 && lp1->lp_entry == lp2->lp_entry) { Ljoin(lp2->LP_BLOCKS,&lp1->LP_BLOCKS); oldcflpx(lp2->lp_extend); diff --git a/util/ego/share/put.c b/util/ego/share/put.c index bbb4aedd6..732377933 100644 --- a/util/ego/share/put.c +++ b/util/ego/share/put.c @@ -386,6 +386,7 @@ putunit(kind,p,l,gf,lf) register bblock_p b; register short n = 0; Lindex pi; + bblock_p nextb; loop_p lp; curoutp = gf; @@ -432,10 +433,12 @@ putunit(kind,p,l,gf,lf) * after it has been written, because there may be references * to it from other (later) blocks. */ - for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) { + for (b = p->p_start; b != (bblock_p) 0; b = nextb) { Ldeleteset(b->b_loops); Ldeleteset(b->b_succ); Ldeleteset(b->b_pred); + /* Must read b->b_next before releasing b */ + nextb = b->b_next; oldbblock(b); } /* Release the memory for the lmap, lbmap, bmap, lpmap tables */ diff --git a/util/ego/ud/ud_copy.c b/util/ego/ud/ud_copy.c index 9546f3a9d..3761dba2d 100644 --- a/util/ego/ud/ud_copy.c +++ b/util/ego/ud/ud_copy.c @@ -59,7 +59,7 @@ STATIC traverse_defs(p,action) def_to_copynr = newtable(nrdefs); cnt = 1; } - if (defcnt > nrdefs) return; + if (defcnt > nrexpldefs) return; for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) { for (l = b->b_start; l != (line_p) 0; l = l->l_next) { if (defs[defcnt] == l) { @@ -75,7 +75,7 @@ STATIC traverse_defs(p,action) } } } - if (++defcnt > nrdefs) return; + if (++defcnt > nrexpldefs) return; } } } -- 2.34.1