summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2014-12-24 18:03:34 +0000
committerschwarze <schwarze@openbsd.org>2014-12-24 18:03:34 +0000
commit0e724740c554c8a1ed447d706e9e8adfe543c94c (patch)
treefa271d83e78255bb0b110ce6afe7433b7145c051
parentPrevent unsigned integer underflow when a number is too wide (diff)
downloadwireguard-openbsd-0e724740c554c8a1ed447d706e9e8adfe543c94c.tar.xz
wireguard-openbsd-0e724740c554c8a1ed447d706e9e8adfe543c94c.zip
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.
-rw-r--r--regress/usr.bin/mandoc/man/RS/width.in6
-rw-r--r--regress/usr.bin/mandoc/man/RS/width.out_ascii2
-rw-r--r--usr.bin/mandoc/man.h3
-rw-r--r--usr.bin/mandoc/man_term.c42
4 files changed, 24 insertions, 29 deletions
diff --git a/regress/usr.bin/mandoc/man/RS/width.in b/regress/usr.bin/mandoc/man/RS/width.in
index c6b1dbf5e2c..e723b583e3b 100644
--- a/regress/usr.bin/mandoc/man/RS/width.in
+++ b/regress/usr.bin/mandoc/man/RS/width.in
@@ -4,6 +4,12 @@ RS-width \- negative and excessive indentation
.SH DESCRIPTION
regular
text
+.RS -14n
+indented
+text
+.RE
+regular
+text
.RS -4n
indented
text
diff --git a/regress/usr.bin/mandoc/man/RS/width.out_ascii b/regress/usr.bin/mandoc/man/RS/width.out_ascii
index 95951e55956..12cd68245e2 100644
--- a/regress/usr.bin/mandoc/man/RS/width.out_ascii
+++ b/regress/usr.bin/mandoc/man/RS/width.out_ascii
@@ -7,6 +7,8 @@ NNAAMMEE
DDEESSCCRRIIPPTTIIOONN
regular text
+indented text
+ regular text
indented text
regular text
indented text
diff --git a/usr.bin/mandoc/man.h b/usr.bin/mandoc/man.h
index 7adf68fea1c..e3d120f5143 100644
--- a/usr.bin/mandoc/man.h
+++ b/usr.bin/mandoc/man.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: man.h,v 1.47 2014/11/28 19:25:03 schwarze Exp $ */
+/* $OpenBSD: man.h,v 1.48 2014/12/24 18:03:34 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -99,6 +99,7 @@ struct man_node {
struct man_node *body; /* BLOCK node BODY ptr */
const struct tbl_span *span; /* TBL */
const struct eqn *eqn; /* EQN */
+ int aux; /* decoded node data, type-dependent */
};
/* Names of macros. Index is enum mant. */
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c
index 314f8fd7325..25224f821ee 100644
--- a/usr.bin/mandoc/man_term.c
+++ b/usr.bin/mandoc/man_term.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: man_term.c,v 1.117 2014/12/24 09:57:41 schwarze Exp $ */
+/* $OpenBSD: man_term.c,v 1.118 2014/12/24 18:03:34 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -45,7 +45,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 {
@@ -278,7 +278,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) {
@@ -641,7 +641,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) {
@@ -838,7 +838,6 @@ static int
pre_RS(DECL_ARGS)
{
struct roffsu su;
- int len;
switch (n->type) {
case MAN_BLOCK:
@@ -850,17 +849,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;
@@ -874,8 +872,6 @@ pre_RS(DECL_ARGS)
static void
post_RS(DECL_ARGS)
{
- struct roffsu su;
- int len;
switch (n->type) {
case MAN_BLOCK:
@@ -887,17 +883,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)