=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.169 retrieving revision 1.170 diff -u -p -r1.169 -r1.170 --- mandoc/roff.c 2011/09/18 14:14:15 1.169 +++ mandoc/roff.c 2011/09/18 23:51:31 1.170 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.169 2011/09/18 14:14:15 schwarze Exp $ */ +/* $Id: roff.c,v 1.170 2011/09/18 23:51:31 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2011 Ingo Schwarze @@ -31,6 +31,9 @@ /* Maximum number of nested if-else conditionals. */ #define RSTACK_MAX 128 +/* Maximum number of string expansions per line, to break infinite loops. */ +#define EXPAND_LIMIT 1000 + enum rofft { ROFF_ad, ROFF_am, @@ -437,10 +440,12 @@ roff_res(struct roff *r, char **bufp, size_t *szp, int const char *stnam; /* start of the name, after "[(*" */ const char *cp; /* end of the name, e.g. before ']' */ const char *res; /* the string to be substituted */ - int i, maxl; + int i, maxl, expand_count; size_t nsz; char *n; + expand_count = 0; + again: cp = *bufp + pos; while (NULL != (cp = strchr(cp, '\\'))) { @@ -535,7 +540,13 @@ again: *bufp = n; *szp = nsz; - goto again; + + if (EXPAND_LIMIT >= ++expand_count) + goto again; + + /* Just leave the string unexpanded. */ + mandoc_msg(MANDOCERR_ROFFLOOP, r->parse, ln, pos, NULL); + return; } }