summaryrefslogtreecommitdiffstats
path: root/man_term.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2014-12-24 18:04:10 +0000
committerIngo Schwarze <schwarze@openbsd.org>2014-12-24 18:04:10 +0000
commit87b33207281eab1594f4681af9e74ecdc86df0ba (patch)
tree83db806ee0d7721264c5971cc7058848b10e24fe /man_term.c
parent9d010e593cd4c985aa8b89549f36c0091dd78cb1 (diff)
downloadmandoc-87b33207281eab1594f4681af9e74ecdc86df0ba.tar.gz
For .RS, we need to save the information how much we actually indented
because negative indents can get truncated, in which case we no longer know how to restore the original indent at the end of the block. This also solves another case of effectively infinite output found by jsg@ with afl, triggered by very large negative indents.
Diffstat (limited to 'man_term.c')
-rw-r--r--man_term.c40
1 files changed, 13 insertions, 27 deletions
diff --git a/man_term.c b/man_term.c
index 713699b5..216b5bb8 100644
--- a/man_term.c
+++ b/man_term.c
@@ -47,7 +47,7 @@ struct mtermp {
#define DECL_ARGS struct termp *p, \
struct mtermp *mt, \
- const struct man_node *n, \
+ struct man_node *n, \
const struct man_meta *meta
struct termact {
@@ -280,7 +280,7 @@ static int
pre_alternate(DECL_ARGS)
{
enum termfont font[2];
- const struct man_node *nn;
+ struct man_node *nn;
int savelit, i;
switch (n->tok) {
@@ -643,7 +643,7 @@ static int
pre_TP(DECL_ARGS)
{
struct roffsu su;
- const struct man_node *nn;
+ struct man_node *nn;
int len, savelit;
switch (n->type) {
@@ -840,7 +840,6 @@ static int
pre_RS(DECL_ARGS)
{
struct roffsu su;
- int len;
switch (n->type) {
case MAN_BLOCK:
@@ -852,17 +851,16 @@ pre_RS(DECL_ARGS)
break;
}
- len = SHRT_MAX + 1;
- if ((n = n->parent->head->child) != NULL &&
- a2roffsu(n->string, &su, SCALE_EN))
- len = term_hspan(p, &su);
- if (len > SHRT_MAX)
- len = term_len(p, p->defindent);
+ n = n->parent->head;
+ n->aux = SHRT_MAX + 1;
+ if (n->child != NULL && a2roffsu(n->child->string, &su, SCALE_EN))
+ n->aux = term_hspan(p, &su);
+ if (n->aux < 0 && (size_t)(-n->aux) > mt->offset)
+ n->aux = -mt->offset;
+ else if (n->aux > SHRT_MAX)
+ n->aux = term_len(p, p->defindent);
- if (len > 0 || (size_t)(-len) < mt->offset)
- mt->offset += len;
- else
- mt->offset = 0;
+ mt->offset += n->aux;
p->offset = mt->offset;
p->rmargin = p->maxrmargin;
@@ -876,8 +874,6 @@ pre_RS(DECL_ARGS)
static void
post_RS(DECL_ARGS)
{
- struct roffsu su;
- int len;
switch (n->type) {
case MAN_BLOCK:
@@ -889,17 +885,7 @@ post_RS(DECL_ARGS)
break;
}
- len = SHRT_MAX + 1;
- if ((n = n->parent->head->child) != NULL &&
- a2roffsu(n->string, &su, SCALE_EN))
- len = term_hspan(p, &su);
- if (len > SHRT_MAX)
- len = term_len(p, p->defindent);
-
- if (len < 0 || (size_t)len < mt->offset)
- mt->offset -= len;
- else
- mt->offset = 0;
+ mt->offset -= n->parent->head->aux;
p->offset = mt->offset;
if (--mt->lmarginsz < MAXMARGINS)