summaryrefslogtreecommitdiffstats
path: root/term_ps.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2016-08-10 11:03:43 +0000
committerIngo Schwarze <schwarze@openbsd.org>2016-08-10 11:03:43 +0000
commitf53337856232ddc04ffaef7792f2ead49eac1224 (patch)
treef9c5db3f7f14563984e62920e401ca19406cb5bb /term_ps.c
parentc3d32c57947c93990ff1080f2a1c0a0cec64d559 (diff)
downloadmandoc-f53337856232ddc04ffaef7792f2ead49eac1224.tar.gz
Fix assertion failures caused by whitespace inside \o'' (overstrike)
sequences that jsg@ found with afl(1): * Avoid writing \t\b in term.c. * Handle trailing \b in term_ps.c.
Diffstat (limited to 'term_ps.c')
-rw-r--r--term_ps.c102
1 files changed, 45 insertions, 57 deletions
diff --git a/term_ps.c b/term_ps.c
index 017a575b..a348f806 100644
--- a/term_ps.c
+++ b/term_ps.c
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015, 2016 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
@@ -98,10 +98,10 @@ static void ps_begin(struct termp *);
static void ps_closepage(struct termp *);
static void ps_end(struct termp *);
static void ps_endline(struct termp *);
-static void ps_fclose(struct termp *);
static void ps_growbuf(struct termp *, size_t);
static void ps_letter(struct termp *, int);
static void ps_pclose(struct termp *);
+static void ps_plast(struct termp *);
static void ps_pletter(struct termp *, int);
static void ps_printf(struct termp *, const char *, ...)
__attribute__((__format__ (printf, 2, 3)));
@@ -780,6 +780,9 @@ ps_end(struct termp *p)
{
size_t i, xref, base;
+ ps_plast(p);
+ ps_pclose(p);
+
/*
* At the end of the file, do one last showpage. This is the
* same behaviour as groff(1) and works for multiple pages as
@@ -1023,39 +1026,53 @@ ps_pclose(struct termp *p)
p->ps->flags &= ~PS_INLINE;
}
+/* If we have a `last' char that wasn't printed yet, print it now. */
static void
-ps_fclose(struct termp *p)
+ps_plast(struct termp *p)
{
+ size_t wx;
+
+ if (p->ps->last == '\0')
+ return;
+
+ /* Check the font mode; open a new scope if it doesn't match. */
+
+ if (p->ps->nextf != p->ps->lastf) {
+ ps_pclose(p);
+ ps_setfont(p, p->ps->nextf);
+ }
+ p->ps->nextf = TERMFONT_NONE;
/*
- * Strong closure: if we have a last-char, spit it out after
- * checking that we're in the right font mode. This will of
- * course open a new scope, if applicable.
- *
- * Following this, close out any scope that's open.
+ * For an overstrike, if a previous character
+ * was wider, advance to center the new one.
*/
- if (p->ps->last != '\0') {
- assert( ! (p->ps->flags & PS_BACKSP));
- if (p->ps->nextf != p->ps->lastf) {
- ps_pclose(p);
- ps_setfont(p, p->ps->nextf);
- }
- p->ps->nextf = TERMFONT_NONE;
- ps_pletter(p, p->ps->last);
- p->ps->last = '\0';
+ if (p->ps->pscolnext) {
+ wx = fonts[p->ps->lastf].gly[(int)p->ps->last-32].wx;
+ if (p->ps->pscol + wx < p->ps->pscolnext)
+ p->ps->pscol = (p->ps->pscol +
+ p->ps->pscolnext - wx) / 2;
}
- if ( ! (PS_INLINE & p->ps->flags))
- return;
+ ps_pletter(p, p->ps->last);
+ p->ps->last = '\0';
- ps_pclose(p);
+ /*
+ * For an overstrike, if a previous character
+ * was wider, advance to the end of the old one.
+ */
+
+ if (p->ps->pscol < p->ps->pscolnext) {
+ ps_pclose(p);
+ p->ps->pscol = p->ps->pscolnext;
+ }
}
static void
ps_letter(struct termp *p, int arg)
{
- size_t savecol, wx;
+ size_t savecol;
char c;
c = arg >= 128 || arg <= 0 ? '?' : arg;
@@ -1121,43 +1138,12 @@ ps_letter(struct termp *p, int arg)
* Use them and print it.
*/
- if (p->ps->last != '\0') {
- if (p->ps->nextf != p->ps->lastf) {
- ps_pclose(p);
- ps_setfont(p, p->ps->nextf);
- }
- p->ps->nextf = TERMFONT_NONE;
-
- /*
- * For an overstrike, if a previous character
- * was wider, advance to center the new one.
- */
-
- if (p->ps->pscolnext) {
- wx = fonts[p->ps->lastf].gly[(int)p->ps->last-32].wx;
- if (p->ps->pscol + wx < p->ps->pscolnext)
- p->ps->pscol = (p->ps->pscol +
- p->ps->pscolnext - wx) / 2;
- }
-
- ps_pletter(p, p->ps->last);
-
- /*
- * For an overstrike, if a previous character
- * was wider, advance to the end of the old one.
- */
-
- if (p->ps->pscol < p->ps->pscolnext) {
- ps_pclose(p);
- p->ps->pscol = p->ps->pscolnext;
- }
- }
+ ps_plast(p);
/*
* Do not print the current character yet because font
- * instructions might follow; only remember it.
- * For the first character, nothing else is done.
- * The final character will get printed from ps_fclose().
+ * instructions might follow; only remember the character.
+ * It will get printed later from ps_plast().
*/
p->ps->last = c;
@@ -1190,7 +1176,8 @@ ps_advance(struct termp *p, size_t len)
* and readjust our column settings.
*/
- ps_fclose(p);
+ ps_plast(p);
+ ps_pclose(p);
p->ps->pscol += len;
}
@@ -1200,7 +1187,8 @@ ps_endline(struct termp *p)
/* Close out any scopes we have open: we're at eoln. */
- ps_fclose(p);
+ ps_plast(p);
+ ps_pclose(p);
/*
* If we're in the margin, don't try to recalculate our current