summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2015-01-15 04:26:39 +0000
committerIngo Schwarze <schwarze@openbsd.org>2015-01-15 04:26:39 +0000
commit581eba212eeec68331e4aa4a904d7c2d72bac114 (patch)
treed24a62288413bfb95754a300f45747756dc9943e
parent23a511d07a0f2e04178f507d768c9e5e7e86f858 (diff)
downloadmandoc-581eba212eeec68331e4aa4a904d7c2d72bac114.tar.gz
Fatal errors no longer exist.
If a file can be opened, mandoc will produce some output; at worst, the output may be almost empty. Simplifies error handling and frees a message type for future use.
-rw-r--r--cgi.c12
-rw-r--r--demandoc.c16
-rw-r--r--libmandoc.h4
-rw-r--r--main.c9
-rw-r--r--man.112
-rw-r--r--man.c3
-rw-r--r--mandoc.190
-rw-r--r--mandoc.331
-rw-r--r--mandoc.h5
-rw-r--r--mandocdb.c13
-rw-r--r--mdoc.c3
-rw-r--r--read.c51
12 files changed, 91 insertions, 158 deletions
diff --git a/cgi.c b/cgi.c
index 8d6c7683..5235b403 100644
--- a/cgi.c
+++ b/cgi.c
@@ -822,7 +822,6 @@ format(const struct req *req, const char *file)
struct man *man;
void *vp;
char *opts;
- enum mandoclevel rc;
int fd;
int usepath;
@@ -832,18 +831,11 @@ format(const struct req *req, const char *file)
}
mchars = mchars_alloc();
- mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL,
+ mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL,
mchars, req->q.manpath);
- rc = mparse_readfd(mp, fd, file);
+ mparse_readfd(mp, fd, file);
close(fd);
- if (rc >= MANDOCLEVEL_FATAL) {
- fprintf(stderr, "fatal mandoc error: %s/%s\n",
- req->q.manpath, file);
- pg_error_internal();
- return;
- }
-
usepath = strcmp(req->q.manpath, req->p[0]);
mandoc_asprintf(&opts,
"fragment,man=%s?query=%%N&sec=%%S%s%s%s%s",
diff --git a/demandoc.c b/demandoc.c
index 2555aac7..5a5369fc 100644
--- a/demandoc.c
+++ b/demandoc.c
@@ -44,7 +44,7 @@ main(int argc, char *argv[])
{
struct mparse *mp;
struct mchars *mchars;
- int ch, i, list;
+ int ch, fd, i, list;
extern int optind;
progname = strrchr(argv[0], '/');
@@ -78,7 +78,7 @@ main(int argc, char *argv[])
argv += optind;
mchars = mchars_alloc();
- mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_FATAL, NULL, mchars, NULL);
+ mp = mparse_alloc(MPARSE_SO, MANDOCLEVEL_BADARG, NULL, mchars, NULL);
assert(mp);
if (0 == argc)
@@ -86,7 +86,11 @@ main(int argc, char *argv[])
for (i = 0; i < argc; i++) {
mparse_reset(mp);
- pmandoc(mp, -1, argv[i], list);
+ if (mparse_open(mp, &fd, argv[i]) != MANDOCLEVEL_OK) {
+ perror(argv[i]);
+ continue;
+ }
+ pmandoc(mp, fd, argv[i], list);
}
mparse_free(mp);
@@ -108,11 +112,7 @@ pmandoc(struct mparse *mp, int fd, const char *fn, int list)
struct man *man;
int line, col;
- if (mparse_readfd(mp, fd, fn) >= MANDOCLEVEL_FATAL) {
- fprintf(stderr, "%s: Parse failure\n", fn);
- return;
- }
-
+ mparse_readfd(mp, fd, fn);
mparse_result(mp, &mdoc, &man, NULL);
line = 1;
col = 0;
diff --git a/libmandoc.h b/libmandoc.h
index 0121b6da..f229466a 100644
--- a/libmandoc.h
+++ b/libmandoc.h
@@ -60,7 +60,7 @@ struct mdoc *mdoc_alloc(struct roff *, struct mparse *,
const char *, int);
void mdoc_reset(struct mdoc *);
int mdoc_parseln(struct mdoc *, int, char *, int);
-int mdoc_endparse(struct mdoc *);
+void mdoc_endparse(struct mdoc *);
void mdoc_addspan(struct mdoc *, const struct tbl_span *);
void mdoc_addeqn(struct mdoc *, const struct eqn *);
@@ -69,7 +69,7 @@ struct man *man_alloc(struct roff *, struct mparse *,
const char *, int);
void man_reset(struct man *);
int man_parseln(struct man *, int, char *, int);
-int man_endparse(struct man *);
+void man_endparse(struct man *);
void man_addspan(struct man *, const struct tbl_span *);
void man_addeqn(struct man *, const struct eqn *);
diff --git a/main.c b/main.c
index 4b6859f8..6c005a66 100644
--- a/main.c
+++ b/main.c
@@ -176,7 +176,7 @@ main(int argc, char *argv[])
memset(&curp, 0, sizeof(struct curparse));
curp.outtype = OUTT_LOCALE;
- curp.wlevel = MANDOCLEVEL_FATAL;
+ curp.wlevel = MANDOCLEVEL_BADARG;
options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1;
defos = NULL;
@@ -647,11 +647,6 @@ parse(struct curparse *curp, int fd, const char *file,
rc = mparse_readfd(curp->mp, fd, file);
- /* Stop immediately if the parse has failed. */
-
- if (MANDOCLEVEL_FATAL <= rc)
- goto cleanup;
-
/*
* With -Wstop and warnings or errors of at least the requested
* level, do not produce output.
@@ -913,7 +908,7 @@ woptions(struct curparse *curp, char *arg)
curp->wlevel = MANDOCLEVEL_ERROR;
break;
case 4:
- curp->wlevel = MANDOCLEVEL_FATAL;
+ curp->wlevel = MANDOCLEVEL_BADARG;
break;
default:
fprintf(stderr, "%s: -W %s: Bad argument\n",
diff --git a/man.1 b/man.1
index 29771ea1..08ec2e23 100644
--- a/man.1
+++ b/man.1
@@ -3,7 +3,7 @@
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
-.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010, 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -300,15 +300,15 @@ to be reported on the standard error output and to affect the exit status.
The
.Ar level
can be
-.Cm warning ,
-.Cm error ,
+.Cm warning
or
-.Cm fatal .
-The default is
-.Cm fatal ;
+.Cm error ;
.Cm all
is an alias for
.Cm warning .
+By default,
+.Nm
+is silent.
See the
.Xr mandoc 1
manual for details.
diff --git a/man.c b/man.c
index 8e8cf725..b58cdd41 100644
--- a/man.c
+++ b/man.c
@@ -109,12 +109,11 @@ man_alloc(struct roff *roff, struct mparse *parse,
return(p);
}
-int
+void
man_endparse(struct man *man)
{
man_macroend(man);
- return(1);
}
int
diff --git a/mandoc.1 b/mandoc.1
index 98d15bec..064fb62c 100644
--- a/mandoc.1
+++ b/mandoc.1
@@ -159,15 +159,15 @@ to be reported on the standard error output and to affect the exit status.
The
.Ar level
can be
-.Cm warning ,
-.Cm error ,
+.Cm warning
or
-.Cm fatal .
-The default is
-.Fl W Ns Cm fatal ;
-.Fl W Ns Cm all
+.Cm error ;
+.Cm all
is an alias for
-.Fl W Ns Cm warning .
+.Cm warning .
+By default,
+.Nm
+is silent.
See
.Sx EXIT STATUS
and
@@ -532,13 +532,11 @@ At least one warning occurred, but no error, and
.Fl W Ns Cm warning
was specified.
.It 3
-At least one parsing error occurred, but no fatal error, and
+At least one parsing error occurred, and
.Fl W Ns Cm error
or
.Fl W Ns Cm warning
was specified.
-.It 4
-A fatal parsing error occurred.
.It 5
Invalid command line arguments were specified.
No input files have been read.
@@ -603,9 +601,6 @@ fields.
.Pp
Message levels have the following meanings:
.Bl -tag -width "warning"
-.It Cm fatal
-The parser is unable to parse a given input file at all.
-No formatted output is produced from that input file.
.It Cm error
An input file contains syntax that cannot be safely interpreted,
either because it is invalid or because
@@ -1277,6 +1272,14 @@ keeps the code more readable.
.El
.Ss "Errors related to roff, mdoc, and man code"
.Bl -ohang
+.It Sy "input too large"
+.Pq mdoc , man
+Currently,
+.Nm
+cannot handle input files larger than its arbitrary size limit
+of 2^31 bytes (2 Gigabytes).
+Since useful manuals are always small, this is not a problem in practice.
+Parsing is aborted as soon as the condition is detected.
.It Sy "input stack limit exceeded, infinite loop?"
.Pq roff
Explicit recursion limits are implemented for the following features,
@@ -1465,6 +1468,29 @@ or
.Ic \&gsize
statement has a non-numeric or negative argument or no argument at all.
The invalid request or statement is ignored.
+.It Sy "NOT IMPLEMENTED: .so with absolute path or \(dq..\(dq"
+.Pq roff
+For security reasons,
+.Nm
+allows
+.Ic \&so
+file inclusion requests only with relative paths
+and only without ascending to any parent directory.
+By requesting the inclusion of a sensitive file, a malicious document
+might otherwise trick a privileged user into inadvertently displaying
+the file on the screen, revealing the file content to bystanders.
+.Nm
+only shows the path as it appears behind
+.Ic \&so .
+.It Sy ".so request failed"
+.Pq roff
+Servicing a
+.Ic \&so
+request requires reading an external file, but the file could not be
+opened.
+.Nm
+only shows the path as it appears behind
+.Ic \&so .
.It Sy "skipping all arguments"
.Pq mdoc , man , eqn , roff
An
@@ -1504,44 +1530,6 @@ macro is invoked with more than one argument, or a request of the
family is invoked with more than two arguments.
The excess arguments are ignored.
.El
-.Ss FATAL errors
-.Bl -ohang
-.It Sy "input too large"
-.Pq mdoc , man
-Currently,
-.Nm
-cannot handle input files larger than its arbitrary size limit
-of 2^31 bytes (2 Gigabytes).
-Since useful manuals are always small, this is not a problem in practice.
-Parsing is aborted as soon as the condition is detected.
-.It Sy "NOT IMPLEMENTED: .so with absolute path or \(dq..\(dq"
-.Pq roff
-For security reasons,
-.Nm
-allows
-.Ic \&so
-file inclusion requests only with relative paths
-and only without ascending to any parent directory.
-By requesting the inclusion of a sensitive file, a malicious document
-might otherwise trick a privileged user into inadvertently displaying
-the file on the screen, revealing the file content to bystanders.
-The parser exits immediately.
-.It Sy ".so request failed"
-.Pq roff
-Servicing a
-.Ic \&so
-request requires reading an external file.
-While trying to do so, an
-.Xr open 2 ,
-.Xr stat 2 ,
-or
-.Xr read 2
-system call failed.
-The parser exits immediately.
-Before showing this message,
-.Nm
-always shows another message explaining why the system call failed.
-.El
.Sh COMPATIBILITY
This section summarises
.Nm
diff --git a/mandoc.3 b/mandoc.3
index 5277f505..630cb52e 100644
--- a/mandoc.3
+++ b/mandoc.3
@@ -1,7 +1,7 @@
.\" $Id$
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010, 2013, 2014, 2015 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
@@ -39,11 +39,10 @@
.Nm mparse_strlevel
.Nm mparse_wait ,
.Nd mandoc macro compiler library
-.Sh LIBRARY
-.Lb libmandoc
.Sh SYNOPSIS
.In sys/types.h
.In mandoc.h
+.Pp
.Fd "#define ASCII_NBRSP"
.Fd "#define ASCII_HYPH"
.Fd "#define ASCII_BREAK"
@@ -176,12 +175,15 @@ initiate a parsing sequence with
and
.Fn mparse_alloc ;
.It
-parse files with
-.Fn mparse_open
-and
+open a file with
+.Xr open 2
+or
+.Fn mparse_open ;
+.It
+parse it with
.Fn mparse_readfd ;
.It
-retrieve a parsed syntax tree, if the parse was successful, with
+retrieve the syntax tree with
.Fn mparse_result ;
.It
iterate over parse nodes with
@@ -208,7 +210,7 @@ and
.Ss Types
.Bl -ohang
.It Vt "enum mandocerr"
-A fatal error, error, or warning message during parsing.
+An error or warning message during parsing.
.It Vt "enum mandoclevel"
A classification of an
.Vt "enum mandocerr"
@@ -229,7 +231,7 @@ This may be used across parsed input if
.Fn mparse_reset
is called between parses.
.It Vt "mandocmsg"
-A prototype for a function to handle fatal error, error, and warning
+A prototype for a function to handle error and warning
messages emitted by the parser.
.El
.Ss Functions
@@ -333,7 +335,7 @@ This is for example useful in
to quickly build minimal databases.
.It Ar wlevel
Can be set to
-.Dv MANDOCLEVEL_FATAL ,
+.Dv MANDOCLEVEL_BADARG ,
.Dv MANDOCLEVEL_ERROR ,
or
.Dv MANDOCLEVEL_WARNING .
@@ -441,14 +443,7 @@ implemented in
.Pa read.c .
.It Fn mparse_result
Obtain the result of a parse.
-Only successful parses
-.Po
-i.e., those where
-.Fn mparse_readfd
-returned less than MANDOCLEVEL_FATAL
-.Pc
-should invoke this function, in which case one of the three pointers will
-be filled in.
+One of the three pointers will be filled in.
Declared in
.In mandoc.h ,
implemented in
diff --git a/mandoc.h b/mandoc.h
index bdd9dd77..d498379d 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -148,6 +148,7 @@ enum mandocerr {
/* related to document structure and macros */
MANDOCERR_FILE, /* cannot open file */
+ MANDOCERR_TOOLARGE, /* input too large */
MANDOCERR_ROFFLOOP, /* input stack limit exceeded, infinite loop? */
MANDOCERR_BADCHAR, /* skipping bad character: number */
MANDOCERR_MACRO, /* skipping unknown macro: macro */
@@ -172,10 +173,6 @@ enum mandocerr {
MANDOCERR_ARG_EXCESS, /* skipping excess arguments: macro ... args */
MANDOCERR_DIVZERO, /* divide by zero */
- MANDOCERR_FATAL, /* ===== start of fatal errors ===== */
-
- MANDOCERR_TOOLARGE, /* input too large */
-
MANDOCERR_MAX
};
diff --git a/mandocdb.c b/mandocdb.c
index b692007f..dd5fa488 100644
--- a/mandocdb.c
+++ b/mandocdb.c
@@ -442,7 +442,7 @@ mandocdb(int argc, char *argv[])
exitcode = (int)MANDOCLEVEL_OK;
mchars = mchars_alloc();
- mp = mparse_alloc(mparse_options, MANDOCLEVEL_FATAL, NULL,
+ mp = mparse_alloc(mparse_options, MANDOCLEVEL_BADARG, NULL,
mchars, NULL);
ohash_init(&mpages, 6, &mpages_info);
ohash_init(&mlinks, 6, &mlinks_info);
@@ -1102,7 +1102,6 @@ mpages_merge(struct mparse *mp)
char *cp;
int fd;
unsigned int pslot;
- enum mandoclevel lvl;
str_info.alloc = hash_alloc;
str_info.calloc = hash_calloc;
@@ -1136,14 +1135,12 @@ mpages_merge(struct mparse *mp)
}
/*
- * Try interpreting the file as mdoc(7) or man(7)
- * source code, unless it is already known to be
- * formatted. Fall back to formatted mode.
+ * Interpret the file as mdoc(7) or man(7) source
+ * code, unless it is known to be formatted.
*/
if (mlink->dform != FORM_CAT || mlink->fform != FORM_CAT) {
- lvl = mparse_readfd(mp, fd, mlink->file);
- if (lvl < MANDOCLEVEL_FATAL)
- mparse_result(mp, &mdoc, &man, &sodest);
+ mparse_readfd(mp, fd, mlink->file);
+ mparse_result(mp, &mdoc, &man, &sodest);
}
if (sodest != NULL) {
diff --git a/mdoc.c b/mdoc.c
index 65368f2d..5039a47d 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -190,12 +190,11 @@ mdoc_alloc(struct roff *roff, struct mparse *parse,
return(p);
}
-int
+void
mdoc_endparse(struct mdoc *mdoc)
{
mdoc_macroend(mdoc);
- return(1);
}
void
diff --git a/read.c b/read.c
index d32f97bb..7ff77224 100644
--- a/read.c
+++ b/read.c
@@ -80,7 +80,7 @@ static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
MANDOCERR_WARNING,
MANDOCERR_WARNING,
MANDOCERR_ERROR,
- MANDOCERR_FATAL,
+ MANDOCERR_MAX,
MANDOCERR_MAX,
MANDOCERR_MAX
};
@@ -192,6 +192,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
/* related to document structure and macros */
NULL,
+ "input too large",
"input stack limit exceeded, infinite loop?",
"skipping bad character",
"skipping unknown macro",
@@ -215,10 +216,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"skipping all arguments",
"skipping excess arguments",
"divide by zero",
-
- "generic fatal error",
-
- "input too large",
};
static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
@@ -545,14 +542,6 @@ rerun:
}
/*
- * If we encounter errors in the recursive parse, make
- * sure we don't continue parsing.
- */
-
- if (MANDOCLEVEL_FATAL <= curp->file_status)
- break;
-
- /*
* If input parsers have not been allocated, do so now.
* We keep these instanced between parsers, but set them
* locally per parse routine since we can use different
@@ -623,10 +612,7 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
if (S_ISREG(st.st_mode)) {
if (st.st_size >= (1U << 31)) {
- curp->file_status = MANDOCLEVEL_FATAL;
- if (curp->mmsg)
- (*curp->mmsg)(MANDOCERR_TOOLARGE,
- curp->file_status, file, 0, 0, NULL);
+ mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL);
return(0);
}
*with_mmap = 1;
@@ -649,11 +635,8 @@ read_whole_file(struct mparse *curp, const char *file, int fd,
for (;;) {
if (off == fb->sz) {
if (fb->sz == (1U << 31)) {
- curp->file_status = MANDOCLEVEL_FATAL;
- if (curp->mmsg)
- (*curp->mmsg)(MANDOCERR_TOOLARGE,
- curp->file_status,
- file, 0, 0, NULL);
+ mandoc_msg(MANDOCERR_TOOLARGE, curp,
+ 0, 0, NULL);
break;
}
resize_buf(fb, 65536);
@@ -679,9 +662,6 @@ static void
mparse_end(struct mparse *curp)
{
- if (MANDOCLEVEL_FATAL <= curp->file_status)
- return;
-
if (curp->mdoc == NULL &&
curp->man == NULL &&
curp->sodest == NULL) {
@@ -695,17 +675,10 @@ mparse_end(struct mparse *curp)
curp->man = curp->pman;
}
}
-
- if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
- assert(MANDOCLEVEL_FATAL <= curp->file_status);
- return;
- }
-
- if (curp->man && ! man_endparse(curp->man)) {
- assert(MANDOCLEVEL_FATAL <= curp->file_status);
- return;
- }
-
+ if (curp->mdoc)
+ mdoc_endparse(curp->mdoc);
+ if (curp->man)
+ man_endparse(curp->man);
roff_endparse(curp->roff);
}
@@ -742,7 +715,7 @@ mparse_parse_buffer(struct mparse *curp, struct buf blk, const char *file)
mparse_buf_r(curp, blk, offset, 1);
- if (0 == --recursion_depth && MANDOCLEVEL_FATAL > curp->file_status)
+ if (--recursion_depth == 0)
mparse_end(curp);
curp->primary = svprimary;
@@ -889,8 +862,6 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg,
{
struct mparse *curp;
- assert(wlevel <= MANDOCLEVEL_FATAL);
-
curp = mandoc_calloc(1, sizeof(struct mparse));
curp->options = options;
@@ -987,7 +958,7 @@ mandoc_msg(enum mandocerr er, struct mparse *m,
{
enum mandoclevel level;
- level = MANDOCLEVEL_FATAL;
+ level = MANDOCLEVEL_ERROR;
while (er < mandoclimits[level])
level--;