summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eqn.c26
-rw-r--r--eqn_parse.h6
-rw-r--r--regress/eqn/define/infinite.in10
-rw-r--r--regress/eqn/define/infinite.out_ascii70
-rw-r--r--regress/eqn/define/infinite.out_lint1
5 files changed, 94 insertions, 19 deletions
diff --git a/eqn.c b/eqn.c
index 9e03079e..272fbf06 100644
--- a/eqn.c
+++ b/eqn.c
@@ -1,7 +1,8 @@
-/* $Id$ */
+/* $Id$ */
/*
+ * Copyright (c) 2014, 2015, 2017, 2018, 2020, 2022
+ * Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014,2015,2017,2018,2020 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -375,19 +376,17 @@ eqn_def_find(struct eqn_node *ep)
static enum eqn_tok
eqn_next(struct eqn_node *ep, enum parse_mode mode)
{
- static int last_len, lim;
-
struct eqn_def *def;
size_t start;
- int diff, i, quoted;
+ int diff, i, newlen, quoted;
enum eqn_tok tok;
/*
* Reset the recursion counter after advancing
- * beyond the end of the previous substitution.
+ * beyond the end of the rightmost substitution.
*/
- if (ep->end - ep->data >= last_len)
- lim = 0;
+ if (ep->end - ep->data >= ep->sublen)
+ ep->subcnt = 0;
ep->start = ep->end;
quoted = mode == MODE_QUOTED;
@@ -434,10 +433,10 @@ eqn_next(struct eqn_node *ep, enum parse_mode mode)
return EQN_TOK__MAX;
if ((def = eqn_def_find(ep)) == NULL)
break;
- if (++lim > EQN_NEST_MAX) {
+ if (++ep->subcnt > EQN_NEST_MAX) {
mandoc_msg(MANDOCERR_ROFFLOOP,
ep->node->line, ep->node->pos, NULL);
- return EQN_TOK_EOF;
+ break;
}
/* Replace a defined name with its string value. */
@@ -446,12 +445,15 @@ eqn_next(struct eqn_node *ep, enum parse_mode mode)
ep->sz += diff;
ep->data = mandoc_realloc(ep->data, ep->sz + 1);
ep->start = ep->data + start;
+ ep->sublen += diff;
}
if (diff)
memmove(ep->start + def->valsz, ep->start + ep->toksz,
strlen(ep->start + ep->toksz) + 1);
memcpy(ep->start, def->val, def->valsz);
- last_len = ep->start - ep->data + def->valsz;
+ newlen = ep->start - ep->data + def->valsz;
+ if (ep->sublen < newlen)
+ ep->sublen = newlen;
}
if (mode != MODE_TOK)
return quoted ? EQN_TOK_QUOTED : EQN_TOK__MAX;
@@ -678,6 +680,8 @@ eqn_parse(struct eqn_node *ep)
return;
ep->start = ep->end = ep->data;
+ ep->sublen = 0;
+ ep->subcnt = 0;
next_tok:
tok = eqn_next(ep, MODE_TOK);
diff --git a/eqn_parse.h b/eqn_parse.h
index bb21a0e1..b16c014f 100644
--- a/eqn_parse.h
+++ b/eqn_parse.h
@@ -1,7 +1,7 @@
-/* $Id$ */
+/* $Id$ */
/*
+ * Copyright (c) 2014, 2017, 2018, 2022 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -32,6 +32,8 @@ struct eqn_node {
size_t defsz; /* Number of definitions. */
size_t sz; /* Length of the source code. */
size_t toksz; /* Length of the current token. */
+ int sublen; /* End of rightmost substitution, so far. */
+ int subcnt; /* Number of recursive substitutions. */
int gsize; /* Default point size. */
int delim; /* In-line delimiters enabled. */
char odelim; /* In-line opening delimiter. */
diff --git a/regress/eqn/define/infinite.in b/regress/eqn/define/infinite.in
index de930fc7..52f0f9d5 100644
--- a/regress/eqn/define/infinite.in
+++ b/regress/eqn/define/infinite.in
@@ -1,4 +1,4 @@
-.\" $OpenBSD: infinite.in,v 1.2 2017/07/04 14:53:23 schwarze Exp $
+.\" $OpenBSD: infinite.in,v 1.3 2022/04/13 20:19:18 schwarze Exp $
.Dd $Mdocdate$
.Dt DEFINE-INFINITE 1
.Os
@@ -29,3 +29,11 @@ trailing position:
define key 'prefix key' key
.EN
eol
+.Pp
+nested expansion:
+.EQ
+define inner "content"
+define outer "inner outer"
+outer
+.EN
+eol
diff --git a/regress/eqn/define/infinite.out_ascii b/regress/eqn/define/infinite.out_ascii
index 7219ce5b..a756abbb 100644
--- a/regress/eqn/define/infinite.out_ascii
+++ b/regress/eqn/define/infinite.out_ascii
@@ -4,12 +4,72 @@ NNAAMMEE
ddeeffiinnee--iinnffiinniittee - infinite recursion in define statements
DDEESSCCRRIIPPTTIIOONN
- alone: eol
+ alone: _k_e_y eol
- leading position: eol
+ leading position: _k_e_y _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x eol
- middle position: eol
+ middle position: _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _k_e_y
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x
+ _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x _s_u_f_f_i_x eol
- trailing position: eol
+ trailing position: _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x _p_r_e_f_i_x
+ _p_r_e_f_i_x _k_e_y eol
-OpenBSD July 4, 2017 OpenBSD
+ nested expansion: _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t
+ _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t
+ _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t
+ _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t
+ _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t
+ _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t
+ _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t
+ _c_o_n_t_e_n_t _c_o_n_t_e_n_t _c_o_n_t_e_n_t _o_u_t_e_r eol
+
+OpenBSD April 13, 2022 OpenBSD
diff --git a/regress/eqn/define/infinite.out_lint b/regress/eqn/define/infinite.out_lint
index 43089bb3..245aa523 100644
--- a/regress/eqn/define/infinite.out_lint
+++ b/regress/eqn/define/infinite.out_lint
@@ -2,3 +2,4 @@ mandoc: infinite.in:10:2: ERROR: input stack limit exceeded, infinite loop?
mandoc: infinite.in:16:2: ERROR: input stack limit exceeded, infinite loop?
mandoc: infinite.in:22:2: ERROR: input stack limit exceeded, infinite loop?
mandoc: infinite.in:28:2: ERROR: input stack limit exceeded, infinite loop?
+mandoc: infinite.in:34:2: ERROR: input stack limit exceeded, infinite loop?