aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2022-06-02 11:29:07 +0000
committerIngo Schwarze <schwarze@openbsd.org>2022-06-02 11:29:07 +0000
commit1ecd7d69278a7a53010b2bdde946bb18930ae850 (patch)
tree64717d1f374ac110b1ac89cb113a09d6808709df
parent47c818f283c63fdbb7882e9aac6e2ab028666c9f (diff)
downloadmandoc-1ecd7d69278a7a53010b2bdde946bb18930ae850.tar.gz
mandoc-1ecd7d69278a7a53010b2bdde946bb18930ae850.tar.zst
mandoc-1ecd7d69278a7a53010b2bdde946bb18930ae850.zip
Avoid the layering violation of re-parsing for \E in roff_expand().
To that end, add another argument to roff_escape() returning the index of the escape name. This also makes the code in roff_escape() a bit more uniform in so far as it no longer needs the "char esc_name" local variable but now does everything with indices into buf[]. No functional change.
-rw-r--r--roff.c15
-rw-r--r--roff_escape.c41
-rw-r--r--roff_int.h2
3 files changed, 26 insertions, 32 deletions
diff --git a/roff.c b/roff.c
index 83701f7d..c4b944e3 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.391 2022/05/31 20:23:05 schwarze Exp $ */
+/* $Id: roff.c,v 1.392 2022/06/02 11:29:07 schwarze Exp $ */
/*
* Copyright (c) 2010-2015, 2017-2022 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -1410,8 +1410,8 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
* it to backslashes and translate backslashes to \e.
*/
- if (roff_escape(buf->buf, ln, pos,
- &iesc, &iarg, &iendarg, &iend) != ESCAPE_EXPAND) {
+ if (roff_escape(buf->buf, ln, pos, &iesc, &inam,
+ &iarg, &iendarg, &iend) != ESCAPE_EXPAND) {
while (pos < iend) {
if (buf->buf[pos] == ec) {
buf->buf[pos] = '\\';
@@ -1428,15 +1428,6 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
continue;
}
- /*
- * Treat "\E" just like "\";
- * it only makes a difference in copy mode.
- */
-
- inam = iesc + 1;
- while (buf->buf[inam] == 'E')
- inam++;
-
/* Handle expansion. */
res = NULL;
diff --git a/roff_escape.c b/roff_escape.c
index 1a5df40f..39011cde 100644
--- a/roff_escape.c
+++ b/roff_escape.c
@@ -41,7 +41,8 @@ mandoc_escape(const char **rendarg, const char **rarg, int *rargl)
int iarg, iendarg, iend;
enum mandoc_esc rval;
- rval = roff_escape(--*rendarg, 0, 0, NULL, &iarg, &iendarg, &iend);
+ rval = roff_escape(--*rendarg, 0, 0,
+ NULL, NULL, &iarg, &iendarg, &iend);
assert(rval != ESCAPE_EXPAND);
if (rarg != NULL)
*rarg = *rendarg + iarg;
@@ -63,20 +64,20 @@ mandoc_escape(const char **rendarg, const char **rarg, int *rargl)
*/
enum mandoc_esc
roff_escape(const char *buf, const int ln, const int aesc,
- int *resc, int *rarg, int *rendarg, int *rend)
+ int *resc, int *rnam, int *rarg, int *rendarg, int *rend)
{
int iesc; /* index of leading escape char */
+ int inam; /* index of escape name */
int iarg; /* index beginning the argument */
int iendarg; /* index right after the argument */
int iend; /* index right after the sequence */
- int sesc, sarg, sendarg, send; /* for sub-escape */
+ int sesc, snam, sarg, sendarg, send; /* for sub-escape */
int maxl; /* expected length of the argument */
int argl; /* actual length of the argument */
int c, i; /* for \[char...] parsing */
int valid_A; /* for \A parsing */
enum mandoc_esc rval; /* return value */
enum mandocerr err; /* diagnostic code */
- char esc_name;
char term; /* byte terminating the argument */
/*
@@ -84,21 +85,20 @@ roff_escape(const char *buf, const int ln, const int aesc,
* it only makes a difference in copy mode.
*/
- iesc = iarg = aesc;
+ iesc = inam = aesc;
do {
- iarg++;
- } while (buf[iarg] == 'E');
+ inam++;
+ } while (buf[inam] == 'E');
/*
* Sort the following cases first by syntax category,
* then by escape sequence type, and finally by ASCII code.
*/
- esc_name = buf[iarg];
- iendarg = iend = ++iarg;
+ iarg = iendarg = iend = inam + 1;
maxl = INT_MAX;
term = '\0';
- switch (esc_name) {
+ switch (buf[inam]) {
/* Escape sequences taking no arguments at all. */
@@ -269,12 +269,12 @@ roff_escape(const char *buf, const int ln, const int aesc,
if ((term == '\b' || (term == '\0' && maxl == INT_MAX)) &&
buf[iarg] == buf[iesc] && roff_escape(buf, ln, iendarg,
- &sesc, &sarg, &sendarg, &send) == ESCAPE_EXPAND)
+ &sesc, &snam, &sarg, &sendarg, &send) == ESCAPE_EXPAND)
goto out_sub;
if (term == '\b') {
- if ((esc_name == 'N' && isdigit((unsigned char)buf[iarg])) ||
- (esc_name == 'h' && strchr(" %&()*+-./0123456789:<=>",
+ if ((buf[inam] == 'N' && isdigit((unsigned char)buf[iarg])) ||
+ (buf[inam] == 'h' && strchr(" %&()*+-./0123456789:<=>",
buf[iarg]) != NULL)) {
iendarg = iend = iarg + 1;
rval = ESCAPE_ERROR;
@@ -282,7 +282,7 @@ roff_escape(const char *buf, const int ln, const int aesc,
}
term = buf[iarg++];
} else if (term == '\0' && maxl == INT_MAX) {
- if (esc_name == 'n' && (buf[iarg] == '+' || buf[iarg] == '-'))
+ if (buf[inam] == 'n' && (buf[iarg] == '+' || buf[iarg] == '-'))
iarg++;
switch (buf[iarg]) {
case '(':
@@ -310,7 +310,7 @@ roff_escape(const char *buf, const int ln, const int aesc,
while (maxl > 0) {
if (buf[iendarg] == '\0') {
/* Ignore an incomplete argument except for \w. */
- if (esc_name != 'w')
+ if (buf[inam] != 'w')
iendarg = iarg;
break;
}
@@ -318,14 +318,14 @@ roff_escape(const char *buf, const int ln, const int aesc,
iend = iendarg + 1;
break;
}
- if (esc_name == 'N' &&
+ if (buf[inam] == 'N' &&
isdigit((unsigned char)buf[iendarg]) == 0) {
iend = iendarg + 1;
break;
}
if (buf[iendarg] == buf[iesc]) {
switch (roff_escape(buf, ln, iendarg,
- &sesc, &sarg, &sendarg, &send)) {
+ &sesc, &snam, &sarg, &sendarg, &send)) {
case ESCAPE_EXPAND:
goto out_sub;
case ESCAPE_UNDEF:
@@ -350,7 +350,7 @@ roff_escape(const char *buf, const int ln, const int aesc,
/* Post-process depending on the content of the argument. */
argl = iendarg - iarg;
- switch (esc_name) {
+ switch (buf[inam]) {
case '*':
if (resc == NULL && argl == 2 &&
buf[iarg] == '.' && buf[iarg + 1] == 'T')
@@ -449,12 +449,15 @@ roff_escape(const char *buf, const int ln, const int aesc,
out_sub:
iesc = sesc;
+ inam = snam;
iarg = sarg;
iendarg = sendarg;
iend = send;
rval = ESCAPE_EXPAND;
out:
+ if (rnam != NULL)
+ *rnam = inam;
if (rarg != NULL)
*rarg = iarg;
if (rendarg != NULL)
@@ -478,7 +481,7 @@ out:
err = MANDOCERR_ESC_UNSUPP;
break;
case ESCAPE_UNDEF:
- if (esc_name == '\\')
+ if (buf[inam] == '\\')
return rval;
err = MANDOCERR_ESC_UNDEF;
break;
diff --git a/roff_int.h b/roff_int.h
index ba7032b0..a26afa98 100644
--- a/roff_int.h
+++ b/roff_int.h
@@ -83,7 +83,7 @@ enum roff_tok roffhash_find(struct ohash *, const char *, size_t);
void roffhash_free(struct ohash *);
enum mandoc_esc roff_escape(const char *, const int, const int,
- int *, int *, int *, int *);
+ int *, int *, int *, int *, int *);
void roff_state_reset(struct roff_man *);
void roff_validate(struct roff_man *);