diff --git a/C/utilpreds.c b/C/utilpreds.c index 10010e758..bfca68683 100644 --- a/C/utilpreds.c +++ b/C/utilpreds.c @@ -30,7 +30,7 @@ typedef struct { } *vcell; -STATIC_PROTO(void copy_complex_term, (CELL *, CELL *, CELL *, CELL *)); +STATIC_PROTO(int copy_complex_term, (CELL *, CELL *, CELL *, CELL *)); STATIC_PROTO(CELL vars_in_complex_term, (CELL *, CELL *)); STATIC_PROTO(Int p_non_singletons_in_term, (void)); STATIC_PROTO(CELL non_singletons_in_complex_term, (CELL *, CELL *)); @@ -54,7 +54,8 @@ clean_tr(tr_fr_ptr TR0) { } } -static void copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL *ptf, CELL *HLow) +static int +copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL *ptf, CELL *HLow) { CELL **to_visit = (CELL **)(HeapTop + sizeof(CELL)); @@ -82,6 +83,9 @@ static void copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL * *ptf = AbsPair(H); ptf++; #ifdef RATIONAL_TREES + if (to_visit + 4 >= (CELL **)H0) { + goto heap_overflow; + } to_visit[0] = pt0; to_visit[1] = pt0_end; to_visit[2] = ptf; @@ -91,6 +95,9 @@ static void copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL * to_visit += 4; #else if (pt0 < pt0_end) { + if (to_visit + 3 >= (CELL **)H0) { + goto heap_overflow; + } to_visit[0] = pt0; to_visit[1] = pt0_end; to_visit[2] = ptf; @@ -126,6 +133,9 @@ static void copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL * ptf++; /* store the terms to visit */ #ifdef RATIONAL_TREES + if (to_visit + 4 >= (CELL **)H0) { + goto heap_overflow; + } to_visit[0] = pt0; to_visit[1] = pt0_end; to_visit[2] = ptf; @@ -135,6 +145,9 @@ static void copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL * to_visit += 4; #else if (pt0 < pt0_end) { + if (to_visit + 3 >= (CELL **)H0) { + goto heap_overflow; + } to_visit[0] = pt0; to_visit[1] = pt0_end; to_visit[2] = ptf; @@ -231,7 +244,7 @@ static void copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL * /* restore our nice, friendly, term to its original state */ HB = HB0; clean_tr(TR0); - return; + return(0); overflow: /* oops, we're in trouble */ @@ -249,6 +262,25 @@ static void copy_complex_term(register CELL *pt0, register CELL *pt0_end, CELL * } #endif clean_tr(TR0); + return(-1); + + heap_overflow: + /* oops, we're in trouble */ + H = HLow; + /* we've done it */ + /* restore our nice, friendly, term to its original state */ + HB = HB0; +#ifdef RATIONAL_TREES + while (to_visit > (CELL **)(HeapTop + sizeof(CELL))) { + to_visit -= 4; + pt0 = to_visit[0]; + pt0_end = to_visit[1]; + ptf = to_visit[2]; + *pt0 = (CELL)to_visit[3]; + } +#endif + clean_tr(TR0); + return(-2); } Term @@ -259,16 +291,25 @@ CopyTerm(Term inp) { #if COROUTINING if (IsAttachedTerm(t)) { CELL *Hi; + int res; restart_attached: *H = t; Hi = H+1; H += 2; - copy_complex_term(Hi-2, Hi-1, Hi, Hi); - if (H == Hi) { /* handle overflow */ - gc(2, ENV, P); - t = Deref(ARG1); - goto restart_attached; + if ((res = copy_complex_term(Hi-2, Hi-1, Hi, Hi)) < 0) { + if (res == -1) { /* handle overflow */ + gc(2, ENV, P); + t = Deref(ARG1); + goto restart_attached; + } else { /* handle overflow */ + if (!growheap(FALSE)) { + Error(SYSTEM_ERROR, TermNil, "YAP failed to reserve space in growheap"); + return(FALSE); + } + t = Deref(ARG1); + goto restart_attached; + } } return(Hi[0]); } @@ -286,11 +327,22 @@ CopyTerm(Term inp) { Hi = H; tf = AbsPair(H); H += 2; - copy_complex_term(ap-1, ap+1, Hi, Hi); - if (H == Hi) { /* handle overflow */ - gc(2, ENV, P); - t = Deref(ARG1); - goto restart_list; + { + int res; + if ((res = copy_complex_term(ap-1, ap+1, Hi, Hi)) < 0) { + if (res == -1) { /* handle overflow */ + gc(2, ENV, P); + t = Deref(ARG1); + goto restart_list; + } else { /* handle overflow */ + if (!growheap(FALSE)) { + Error(SYSTEM_ERROR, TermNil, "YAP failed to reserve space in growheap"); + return(FALSE); + } + t = Deref(ARG1); + goto restart_list; + } + } } return(tf); } else { @@ -306,11 +358,22 @@ CopyTerm(Term inp) { tf = AbsAppl(H); H[0] = (CELL)f; H += 1+ArityOfFunctor(f); - copy_complex_term(ap, ap+ArityOfFunctor(f), HB0+1, HB0); - if (H == HB0) { - gc(2, ENV, P); - t = Deref(ARG1); - goto restart_appl; + { + int res; + if ((res = copy_complex_term(ap, ap+ArityOfFunctor(f), HB0+1, HB0)) < 0) { + if (res == -1) { + gc(2, ENV, P); + t = Deref(ARG1); + goto restart_appl; + } else { /* handle overflow */ + if (!growheap(FALSE)) { + Error(SYSTEM_ERROR, TermNil, "YAP failed to reserve space in growheap"); + return(FALSE); + } + t = Deref(ARG1); + goto restart_appl; + } + } } return(tf); }