-/* $Id: roff.c,v 1.283 2015/10/22 21:54:23 schwarze Exp $ */
+/* $Id: roff.c,v 1.293 2017/03/09 15:29:35 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2015, 2017 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
n->sec = man->lastsec;
if (man->flags & MDOC_SYNOPSIS)
- n->flags |= MDOC_SYNPRETTY;
+ n->flags |= NODE_SYNPRETTY;
else
- n->flags &= ~MDOC_SYNPRETTY;
+ n->flags &= ~NODE_SYNPRETTY;
if (man->flags & MDOC_NEWLINE)
- n->flags |= MDOC_LINE;
+ n->flags |= NODE_LINE;
man->flags &= ~MDOC_NEWLINE;
return n;
n->parent = man->last->parent;
break;
case ROFF_NEXT_CHILD:
+ if (man->last->child != NULL) {
+ n->next = man->last->child;
+ man->last->child->prev = n;
+ } else
+ man->last->last = n;
man->last->child = n;
n->parent = man->last;
- n->parent->last = n;
break;
default:
abort();
}
- n->parent->nchild++;
man->last = n;
switch (n->type) {
n = roff_node_alloc(man, line, pos, ROFFT_TEXT, TOKEN_NONE);
n->string = roff_strdup(man->roff, word);
roff_node_append(man, n);
- if (man->macroset == MACROSET_MDOC)
- n->flags |= MDOC_VALID | MDOC_ENDED;
- else
- n->flags |= MAN_VALID;
+ n->flags |= NODE_VALID | NODE_ENDED;
man->next = ROFF_NEXT_SIBLING;
}
n = roff_node_alloc(man, eqn->ln, eqn->pos, ROFFT_EQN, TOKEN_NONE);
n->eqn = eqn;
if (eqn->ln > man->last->line)
- n->flags |= MDOC_LINE;
+ n->flags |= NODE_LINE;
roff_node_append(man, n);
man->next = ROFF_NEXT_SIBLING;
}
n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE);
n->span = tbl;
roff_node_append(man, n);
- if (man->macroset == MACROSET_MDOC)
- n->flags |= MDOC_VALID | MDOC_ENDED;
- else
- n->flags |= MAN_VALID;
+ n->flags |= NODE_VALID | NODE_ENDED;
man->next = ROFF_NEXT_SIBLING;
}
/* Adjust parent. */
if (n->parent != NULL) {
- n->parent->nchild--;
if (n->parent->child == n)
n->parent->child = n->next;
if (n->parent->last == n)
while (n->child != NULL)
roff_node_delete(man, n->child);
- assert(n->nchild == 0);
roff_node_unlink(man, n);
roff_node_free(n);
}
return;
}
- /* Skip leading whitespace and escape sequences. */
+ /* Skip leading whitespace. */
- cp = n->string;
- while (*cp != '\0') {
- if ('\\' == *cp) {
+ for (cp = n->string; *cp != '\0'; cp++) {
+ if (cp[0] == '\\' && cp[1] != '\0' &&
+ strchr(" %&0^|~", cp[1]) != NULL)
cp++;
- mandoc_escape((const char **)&cp, NULL, NULL);
- } else if (isspace((unsigned char)*cp))
- cp++;
- else
+ else if ( ! isspace((unsigned char)*cp))
break;
}
+ /* Skip trailing backslash. */
+
+ sz = strlen(cp);
+ if (sz > 0 && cp[sz - 1] == '\\')
+ sz--;
+
/* Skip trailing whitespace. */
- for (sz = strlen(cp); sz; sz--)
+ for (; sz; sz--)
if ( ! isspace((unsigned char)cp[sz-1]))
break;
return ROFF_IGN;
while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ')
pos++;
- while (buf->buf[pos] != '\0' && buf->buf[pos] == ' ')
+ while (buf->buf[pos] == ' ')
pos++;
return tbl_read(r->tbl, ln, buf->buf, pos);
}
{
const char *arg[9], *ap;
char *cp, *n1, *n2;
- int i, ib, ie;
+ int expand_count, i, ib, ie;
size_t asz, rsz;
/*
*/
buf->sz = strlen(r->current_string) + 1;
- n1 = cp = mandoc_malloc(buf->sz);
+ n1 = n2 = cp = mandoc_malloc(buf->sz);
memcpy(n1, r->current_string, buf->sz);
+ expand_count = 0;
while (*cp != '\0') {
/* Scan ahead for the next argument invocation. */
}
cp -= 2;
+ /*
+ * Prevent infinite recursion.
+ */
+
+ if (cp >= n2)
+ expand_count = 1;
+ else if (++expand_count > EXPAND_LIMIT) {
+ mandoc_msg(MANDOCERR_ROFFLOOP, r->parse,
+ ln, (int)(cp - n1), NULL);
+ free(buf->buf);
+ buf->buf = n1;
+ return ROFF_IGN;
+ }
+
/*
* Determine the size of the expanded argument,
* taking escaping of quotes into account.
ssz = 0;
while ('\0' != *p) {
- if ('\\' != *p && r->xtab && r->xtab[(int)*p].p) {
+ assert((unsigned int)*p < 128);
+ if ('\\' != *p && r->xtab && r->xtab[(unsigned int)*p].p) {
sz = r->xtab[(int)*p].sz;
res = mandoc_realloc(res, ssz + sz + 1);
memcpy(res + ssz, r->xtab[(int)*p].p, sz);