summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2017-03-07 20:00:08 +0000
committerIngo Schwarze <schwarze@openbsd.org>2017-03-07 20:00:08 +0000
commit0048f6b4d138a5084ab0895e54f81bfa74d70f76 (patch)
treeec3e7d582b64f0f9f1ef6029f20f4a4a52806f1a
parent26f4474f228f82cd5061c568f57cb6fec975c194 (diff)
downloadmandoc-0048f6b4d138a5084ab0895e54f81bfa74d70f76.tar.gz
If a user-defined macro is aborted because it exceeds the stack
limit, usually due to infinite recursion, discard whatever remains in all those open stack levels. Otherwise, insane constructions like the following could generate macros of enormous size, causing mandoc(1) to die from memory exhaustion: .de m \" original macro definition .m \" recursion to blow up the stack .de m \" definition to be run during the call of .m marked (*) very long plain text (some kilobytes) .m \" expand the above a thousand times while unwinding the stack .. \" end of the original definition .m \" (*) recursively generate a ridiculously large macro .. \" end of recursively generated definition .m \" execute the giant macro, exhausting memory Very creative abuse found by tb@ with afl(1).
-rw-r--r--read.c20
-rw-r--r--regress/roff/de/Makefile9
-rw-r--r--regress/roff/de/infinite.in14
-rw-r--r--regress/roff/de/infinite.out_ascii9
-rw-r--r--regress/roff/de/infinite.out_lint1
5 files changed, 43 insertions, 10 deletions
diff --git a/read.c b/read.c
index 71eb3976..6ffc1d91 100644
--- a/read.c
+++ b/read.c
@@ -66,7 +66,7 @@ struct mparse {
static void choose_parser(struct mparse *);
static void resize_buf(struct buf *, size_t);
-static void mparse_buf_r(struct mparse *, struct buf, size_t, int);
+static int mparse_buf_r(struct mparse *, struct buf, size_t, int);
static int read_whole_file(struct mparse *, const char *, int,
struct buf *, int *);
static void mparse_end(struct mparse *);
@@ -310,7 +310,7 @@ choose_parser(struct mparse *curp)
* macros, inline equations, and input line traps)
* and indirectly (for .so file inclusion).
*/
-static void
+static int
mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start)
{
const struct tbl_span *span;
@@ -511,13 +511,16 @@ rerun:
switch (rr) {
case ROFF_REPARSE:
- if (REPARSE_LIMIT >= ++curp->reparse_count)
- mparse_buf_r(curp, ln, of, 0);
- else
+ if (++curp->reparse_count > REPARSE_LIMIT)
mandoc_msg(MANDOCERR_ROFFLOOP, curp,
curp->line, pos, NULL);
- pos = 0;
- continue;
+ else if (mparse_buf_r(curp, ln, of, 0) == 1 ||
+ start == 1) {
+ pos = 0;
+ continue;
+ }
+ free(ln.buf);
+ return 0;
case ROFF_APPEND:
pos = strlen(ln.buf);
continue;
@@ -531,7 +534,7 @@ rerun:
(i >= blk.sz || blk.buf[i] == '\0')) {
curp->sodest = mandoc_strdup(ln.buf + of);
free(ln.buf);
- return;
+ return 1;
}
/*
* We remove `so' clauses from our lookaside
@@ -597,6 +600,7 @@ rerun:
}
free(ln.buf);
+ return 1;
}
static int
diff --git a/regress/roff/de/Makefile b/regress/roff/de/Makefile
index 9488ce05..43bcf00f 100644
--- a/regress/roff/de/Makefile
+++ b/regress/roff/de/Makefile
@@ -1,7 +1,12 @@
# $OpenBSD: Makefile,v 1.9 2015/02/03 19:37:25 schwarze Exp $
-REGRESS_TARGETS = append cond escname factorial indir startde TH Dd
-LINT_TARGETS = escname indir
+REGRESS_TARGETS = append cond escname factorial indir infinite startde TH Dd
+LINT_TARGETS = escname indir infinite
+
+# groff-1.22.3 defect:
+# infinite recursion aborts output completely
+
+SKIP_GROFF = infinite
.include <bsd.regress.mk>
diff --git a/regress/roff/de/infinite.in b/regress/roff/de/infinite.in
new file mode 100644
index 00000000..683eba7f
--- /dev/null
+++ b/regress/roff/de/infinite.in
@@ -0,0 +1,14 @@
+.Dd March 7, 2017
+.Dt DE-INFINITE 1
+.Os OpenBSD
+.Sh NAME
+.Nm de-infinite
+.Nd inifinte recursion in a user-defined macro
+.Sh DESCRIPTION
+initial text
+.de mym
+.mym
+not printed
+..
+.mym
+final text
diff --git a/regress/roff/de/infinite.out_ascii b/regress/roff/de/infinite.out_ascii
new file mode 100644
index 00000000..7f8210ab
--- /dev/null
+++ b/regress/roff/de/infinite.out_ascii
@@ -0,0 +1,9 @@
+DE-INFINITE(1) General Commands Manual DE-INFINITE(1)
+
+NNAAMMEE
+ ddee--iinnffiinniittee - inifinte recursion in a user-defined macro
+
+DDEESSCCRRIIPPTTIIOONN
+ initial text final text
+
+OpenBSD March 7, 2017 OpenBSD
diff --git a/regress/roff/de/infinite.out_lint b/regress/roff/de/infinite.out_lint
new file mode 100644
index 00000000..168c7be4
--- /dev/null
+++ b/regress/roff/de/infinite.out_lint
@@ -0,0 +1 @@
+mandoc: infinite.in:13:5: ERROR: input stack limit exceeded, infinite loop?