From: NeilBrown Date: Thu, 14 Sep 2023 04:14:09 +0000 (+1000) Subject: Explicitly guard against infinite loops in consistency check. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=ea6780cb7cb7887c4ad4db68d28df06184a764d2;p=edlib.git Explicitly guard against infinite loops in consistency check. We don't want the consistency check to introduce instability. So make sure they don't loop indefinitely - either due to corrupted list or just very large lists. Signed-off-by: NeilBrown --- diff --git a/DOC/TODO.md b/DOC/TODO.md index 043b199e..9e532bfa 100644 --- a/DOC/TODO.md +++ b/DOC/TODO.md @@ -127,7 +127,7 @@ Core features - [ ] catching doc:replace in a pane doesn't catch doc:insert-file. I need a simple way to intercept any change. - [X] switch-buffer in pop-up window - shouldn't kill the popup (does it?) -- [ ] explicitly guard against infinite loops in consistency checks +- [X] explicitly guard against infinite loops in consistency checks - [ ] skip consistency checks after several with no stop for input. - [ ] unwanted docs too easily appear high in recent-list - *Output* - [ ] design a way for a keystroke to interrupt a long-running function. diff --git a/core-mark.c b/core-mark.c index b110cf14..7f4d8e2b 100644 --- a/core-mark.c +++ b/core-mark.c @@ -1200,6 +1200,7 @@ void doc_check_consistent(struct doc *d safe) struct mark *m, *m2 = NULL; int seq = 0; int i; + int max = 1000; static bool warned = False; hlist_for_each_entry(m, &d->marks, all) { @@ -1214,6 +1215,8 @@ void doc_check_consistent(struct doc *d safe) warned = True; } m2 = m; + if (max-- < 0) + break; } for (i = 0; d->views && i < d->nviews; i++) if (d->views[i].owner == NULL) { @@ -1239,6 +1242,8 @@ void doc_check_consistent(struct doc *d safe) if (m->seq < seq) abort(); seq = m->seq + 1; + if (max-- < 0) + break; } } } @@ -1249,11 +1254,15 @@ bool marks_validate(struct mark *m1 safe, struct mark *m2 safe) struct doc *d = m1->owner->data; int found = 0; int ret; + int max = 1000; if (m1 == m2) { - for (m = mark_first(d); m; m = mark_next(m)) + for (m = mark_first(d); m; m = mark_next(m)) { if (m1 == m) return True; + if (max-- < 0) + break; + } LOG("marks_validate: marks not found"); return False; } @@ -1261,9 +1270,12 @@ bool marks_validate(struct mark *m1 safe, struct mark *m2 safe) m = m1; m1 = m2; m2 = m; } - for (m = mark_first(d); m; m = mark_next(m)) + for (m = mark_first(d); m; m = mark_next(m)) { if (m == m1 || m == m2) found += 1; + if (max-- < 0) + break; + } if (found != 2) { LOG("log_val_marks not both found, only %d", found); return False; diff --git a/doc-multipart.c b/doc-multipart.c index 1f262c5f..8edcdfd9 100644 --- a/doc-multipart.c +++ b/doc-multipart.c @@ -152,12 +152,12 @@ static void mp_mark_refcnt(struct mark *m safe, int inc) static void mp_check_consistent(struct mp_info *mpi safe) { -// struct mark *m; struct doc *d = &mpi->doc; -// int s = -1; - - doc_check_consistent(d); #if 0 + struct mark *m; + int s = -1; + int max = 1000; + for (m = mark_first(d); m; m = mark_next(m)) { if (!m->ref.m || m->ref.m->seq <= s) { for (m = mark_first(d); m; @@ -169,9 +169,11 @@ static void mp_check_consistent(struct mp_info *mpi safe) abort(); } s = m->ref.m->seq; + if (max-- < 0) + break; } - doc_check_consistent(d); #endif + doc_check_consistent(d); } static void change_part(struct mp_info *mpi safe, struct mark *m safe, diff --git a/doc-text.c b/doc-text.c index 8d528f39..46c3c348 100644 --- a/doc-text.c +++ b/doc-text.c @@ -2087,16 +2087,20 @@ static void text_check_consistent(struct text *t safe) struct text_chunk *c; struct mark *m, *prev; struct doc *d = &t->doc; - int loops; + int loops = 10000; list_for_each_entry(c, &t->text, lst) { check_allocated(t, c->txt, c->end); if (c->start >= c->end) abort(); + if (loops-- < 0) + break; } list_for_each_entry(c, &t->text, lst) { struct text_chunk *c2; list_for_each_entry(c2, &t->text, lst) { + if (loops -- < 0) + break; if (c2 == c || c2->txt != c->txt) continue; @@ -2106,12 +2110,13 @@ static void text_check_consistent(struct text *t safe) continue; abort(); } + if (loops-- < 0) + break; } /* This test is quadratic in the number of marks, so let's * give up rather then annoy the users. */ - loops = 10000; for (m = mark_first(d); m; m = mark_next(m)) text_ref_consistent(t, &m->ref, &loops); @@ -2130,6 +2135,8 @@ static void text_check_consistent(struct text *t safe) } } prev = m; + if (loops-- < 0) + break; } doc_check_consistent(d); }