diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2016-08-10 11:03:43 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2016-08-10 11:03:43 +0000 |
commit | f53337856232ddc04ffaef7792f2ead49eac1224 (patch) | |
tree | f9c5db3f7f14563984e62920e401ca19406cb5bb | |
parent | c3d32c57947c93990ff1080f2a1c0a0cec64d559 (diff) | |
download | mandoc-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.
-rw-r--r-- | term.c | 8 | ||||
-rw-r--r-- | term_ps.c | 102 |
2 files changed, 50 insertions, 60 deletions
@@ -1,7 +1,7 @@ /* $Id$ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010-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 @@ -504,7 +504,9 @@ term_word(struct termp *p, const char *word) } } /* Trim trailing backspace/blank pair. */ - if (p->col > 2 && p->buf[p->col - 1] == ' ') + if (p->col > 2 && + (p->buf[p->col - 1] == ' ' || + p->buf[p->col - 1] == '\t')) p->col -= 2; continue; default: @@ -568,7 +570,7 @@ encode1(struct termp *p, int c) p->fontq[p->fonti] : TERMFONT_NONE; if (p->flags & TERMP_BACKBEFORE) { - if (p->buf[p->col - 1] == ' ') + if (p->buf[p->col - 1] == ' ' || p->buf[p->col - 1] == '\t') p->col--; else p->buf[p->col++] = 8; @@ -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 |