From: Ingo Schwarze <schwarze@usta.de>
To: tech@mdocml.bsd.lv
Subject: Re: implement .so
Date: Mon, 25 Oct 2010 23:55:06 +0200 [thread overview]
Message-ID: <20101025215506.GA12557@iris.usta.de> (raw)
In-Reply-To: <20101024195135.GA1809@britannica.bec.de>
Hi Joerg,
Joerg Sonnenberger wrote on Sun, Oct 24, 2010 at 09:51:35PM +0200:
> As we have seen in Rostock, full .so implementation has some funny side
> effects, so I consider it a broken feature.
Yes, no doubt. It is broken by design in multiple ways.
> I won't oppose a clean patch, we have already seen that it is
> straight forward to implement.
See below, feedback is welcome.
After the first round of review and polishing here
i'm planning to commit it to OpenBSD and have it looked
over by a few people round here.
> My point is that it essentially falls apart if you want to use
> compressed man pages.
Sure, i understand that.
> So it really, really shouldn't be used.
I fully agree.
This is to deal with existing stuff
and should not be used for new projects.
> Sorry, yes. Only allow relative path names without /../ components.
Actually, it is even worse.
All ports in the OpenBSD ports tree using the feature give the path
relative to the *parent* directory of the directory containing the
manual page having the .so directive.
So these are neither absolute paths (relative to the root of the
file system) nor relative paths (relative to the current working
directory).
What i'm doing for now is:
* regarding validation of the .so directive (roff.c, roff_so()):
- path must start with "man"
- path must contain exactly one '/'
- the characters before and after the slash must not be '.'
- the slash must not be the last character
* regarding validation of the path to the page containing
the .so directive (main.c, pfile()):
- path must contain at least one '/'
- component before the slash must start with "man"
In this case, i replace the last two components of the path to
the page containing the .so directive by the contents of the
directive, or else error out.
Note that the patch builds upon the preceding refactoring patch
i sent yesterday, both building on the OpenBSD tree.
Yours,
Ingo
diff -Napur mandoc.pdesc/main.c mandoc/main.c
--- mandoc.pdesc/main.c Sun Oct 24 13:47:06 2010
+++ mandoc/main.c Mon Oct 25 15:02:52 2010
@@ -15,6 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -173,6 +174,8 @@ static const char * const mandocerrs[MANDOCERR_MAX] =
"argument count wrong, violates syntax",
"child violates parent syntax",
"argument count wrong, violates syntax",
+ "invalid path in include directive",
+ "include used by a file at an invalid path",
"no document body",
"no document prologue",
"static buffer exhausted",
@@ -181,6 +184,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] =
static void pdesc(struct curparse *);
static void fdesc(struct curparse *);
static void ffile(const char *, struct curparse *);
+static int pfile(const char *, struct curparse *, int);
static int moptions(enum intt *, char *);
static int mmsg(enum mandocerr, void *,
int, int, const char *);
@@ -306,7 +310,58 @@ ffile(const char *file, struct curparse *curp)
perror(curp->file);
}
+static int
+pfile(const char *file, struct curparse *curp, int ln)
+{
+ char path[MAXPATHLEN];
+ const char *savefile;
+ char *p;
+ int savefd;
+ if (strlcpy(path, curp->file, sizeof(path)) >= sizeof(path)) {
+ mmsg(MANDOCERR_MEM, curp, ln, 1, NULL);
+ return(0);
+ }
+
+ if (NULL == (p = strrchr(path, '/'))) {
+ mmsg(MANDOCERR_SOUSER, curp, ln, 1, NULL);
+ return(0);
+ }
+
+ while (path < p && '/' != p[-1])
+ p--;
+
+ if (strncmp(p, "man", 3)) {
+ mmsg(MANDOCERR_SOUSER, curp, ln, 1, NULL);
+ return(0);
+ }
+ *p = '\0';
+
+ if (strlcat(path, file, sizeof(path)) >= sizeof(path)) {
+ mmsg(MANDOCERR_MEM, curp, ln, 1, NULL);
+ return(0);
+ }
+
+ savefile = curp->file;
+ savefd = curp->fd;
+
+ curp->file = path;
+ if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
+ perror(curp->file);
+ exit_status = MANDOCLEVEL_SYSERR;
+ } else {
+ pdesc(curp);
+ if (-1 == close(curp->fd))
+ perror(curp->file);
+ }
+
+ curp->file = savefile;
+ curp->fd = savefd;
+
+ return(MANDOCLEVEL_FATAL > exit_status ? 1 : 0);
+}
+
+
static void
resize_buf(struct buf *buf, size_t initial)
{
@@ -629,6 +684,11 @@ pdesc(struct curparse *curp)
} else if (ROFF_ERR == re) {
assert(MANDOCLEVEL_FATAL <= exit_status);
break;
+ } else if (ROFF_SO == re) {
+ if (pfile(ln.buf + of, curp, lnn_start))
+ continue;
+ else
+ break;
}
/*
diff -Napur mandoc.pdesc/mandoc.h mandoc/mandoc.h
--- mandoc.pdesc/mandoc.h Sun Oct 24 13:47:06 2010
+++ mandoc/mandoc.h Mon Oct 25 14:57:22 2010
@@ -114,6 +114,8 @@ enum mandocerr {
MANDOCERR_SYNTARGVCOUNT, /* argument count wrong, violates syntax */
MANDOCERR_SYNTCHILD, /* child violates parent syntax */
MANDOCERR_SYNTARGCOUNT, /* argument count wrong, violates syntax */
+ MANDOCERR_SOPATH, /* invalid path in include directive */
+ MANDOCERR_SOUSER, /* include used by a file at an invalid path */
MANDOCERR_NODOCBODY, /* no document body */
MANDOCERR_NODOCPROLOG, /* no document prologue */
MANDOCERR_MEM, /* static buffer exhausted */
diff -Napur mandoc.pdesc/roff.c mandoc/roff.c
--- mandoc.pdesc/roff.c Wed Oct 20 09:22:11 2010
+++ mandoc/roff.c Mon Oct 25 14:38:24 2010
@@ -48,11 +48,12 @@ enum rofft {
ROFF_ie,
ROFF_if,
ROFF_ig,
+ ROFF_nr,
ROFF_rm,
+ ROFF_so,
ROFF_tr,
ROFF_cblock,
ROFF_ccond, /* FIXME: remove this. */
- ROFF_nr,
ROFF_MAX
};
@@ -128,6 +129,7 @@ static int roff_res(struct roff *,
char **, size_t *, int);
static void roff_setstr(struct roff *,
const char *, const char *);
+static enum rofferr roff_so(ROFF_ARGS);
static char *roff_strdup(const char *);
/* See roff_hash_find() */
@@ -150,11 +152,12 @@ static struct roffmac roffs[ROFF_MAX] = {
{ "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
{ "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+ { "nr", roff_nr, NULL, NULL, 0, NULL },
{ "rm", roff_line, NULL, NULL, 0, NULL },
+ { "so", roff_so, NULL, NULL, 0, NULL },
{ "tr", roff_line, NULL, NULL, 0, NULL },
{ ".", roff_cblock, NULL, NULL, 0, NULL },
{ "\\}", roff_ccond, NULL, NULL, 0, NULL },
- { "nr", roff_nr, NULL, NULL, 0, NULL },
};
static void roff_free1(struct roff *);
@@ -1005,6 +1008,26 @@ roff_nr(ROFF_ARGS)
}
return(ROFF_IGN);
+}
+
+
+/* ARGSUSED */
+static enum rofferr
+roff_so(ROFF_ARGS)
+{
+ char *name, *p;
+
+ name = *bufp + pos;
+ if (strncmp(name, "man", 3) ||
+ NULL == (p = strchr(name, '/')) ||
+ '.' == p[-1] || '.' == p[1] || '\0' == p[1] ||
+ strchr(p+1, '/')) {
+ (*r->msg)(MANDOCERR_SOPATH, r->data, ln, pos, NULL);
+ return(ROFF_ERR);
+ }
+
+ *offs = pos;
+ return(ROFF_SO);
}
diff -Napur mandoc.pdesc/roff.h mandoc/roff.h
--- mandoc.pdesc/roff.h Wed Oct 20 09:22:11 2010
+++ mandoc/roff.h Mon Oct 25 03:48:01 2010
@@ -20,6 +20,7 @@
enum rofferr {
ROFF_CONT, /* continue processing line */
ROFF_RERUN, /* re-run roff interpreter with offset */
+ ROFF_SO, /* include another file */
ROFF_IGN, /* ignore current line */
ROFF_ERR /* badness: puke and stop */
};
--
To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv
next prev parent reply other threads:[~2010-10-25 21:55 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-24 16:40 Ingo Schwarze
2010-10-24 16:49 ` Joerg Sonnenberger
2010-10-24 17:29 ` Ingo Schwarze
2010-10-24 17:38 ` Joerg Sonnenberger
2010-10-24 18:00 ` Ingo Schwarze
2010-10-24 18:15 ` Joerg Sonnenberger
2010-10-24 18:17 ` Joerg Sonnenberger
2010-10-24 19:41 ` Ingo Schwarze
2010-10-24 19:51 ` Joerg Sonnenberger
2010-10-25 21:55 ` Ingo Schwarze [this message]
2010-10-25 22:10 ` Joerg Sonnenberger
2010-10-26 17:59 ` Ingo Schwarze
2010-10-26 18:12 ` Joerg Sonnenberger
2010-10-26 21:48 ` Ingo Schwarze
2010-10-26 21:56 ` Joerg Sonnenberger
2010-10-26 23:10 ` Ingo Schwarze
2010-10-26 23:30 ` Joerg Sonnenberger
2010-10-26 23:41 ` Ingo Schwarze
2010-10-27 9:34 ` Kristaps Dzonsons
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101025215506.GA12557@iris.usta.de \
--to=schwarze@usta.de \
--cc=tech@mdocml.bsd.lv \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).