summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-01-03 23:39:28 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-01-03 23:39:28 +0000
commit8e6a3ab86e7918f82355f33fa944cca1df578195 (patch)
tree41bcb6b2a6fd1c8edf1a0deb8d676d9b196479c5
parent60a5e3c43953dd77bf29755321b3d66b06f98807 (diff)
Partial cleanup of argument count validation in mdoc(7):
* Do not segfault on empty .Db, .Rs, .Sm, and .St. * Let check_count() really throw the requested level, not always ERROR. * Downgrade most bad argument counts from ERROR to WARNING. * And some related internal cleanup. Looks fine to kristaps@. Note that the macros using eerr_ge1() still need to be checked at a later time; but as all the others are done, let's use what we already have.
-rw-r--r--usr.bin/mandoc/main.c3
-rw-r--r--usr.bin/mandoc/mandoc.h3
-rw-r--r--usr.bin/mandoc/mdoc_validate.c131
3 files changed, 70 insertions, 67 deletions
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index c35f87f4ed3..116d051262c 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.62 2010/12/21 01:22:00 schwarze Exp $ */
+/* $Id: main.c,v 1.63 2011/01/03 23:39:27 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -138,6 +138,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
/* related to missing macro arguments */
"skipping empty macro",
+ "argument count wrong",
"missing display type",
"list type must come first",
"tag lists require a width argument",
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h
index 215f8d53650..e30929c9521 100644
--- a/usr.bin/mandoc/mandoc.h
+++ b/usr.bin/mandoc/mandoc.h
@@ -1,4 +1,4 @@
-/* $Id: mandoc.h,v 1.25 2010/12/09 23:01:18 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.26 2011/01/03 23:39:27 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -75,6 +75,7 @@ enum mandocerr {
/* related to missing macro arguments */
MANDOCERR_MACROEMPTY, /* skipping empty macro */
+ MANDOCERR_ARGCWARN, /* argument count wrong */
MANDOCERR_DISPTYPE, /* missing display type */
MANDOCERR_LISTFIRST, /* list type must come first */
MANDOCERR_NOWIDTHARG, /* tag lists require a width argument */
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index f91a3b0a6d2..6cab7c65ca7 100644
--- a/usr.bin/mandoc/mdoc_validate.c
+++ b/usr.bin/mandoc/mdoc_validate.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_validate.c,v 1.82 2010/12/29 00:47:31 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.83 2011/01/03 23:39:27 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -53,7 +53,6 @@ enum check_ineq {
enum check_lvl {
CHECK_WARN,
CHECK_ERROR,
- CHECK_FATAL
};
typedef int (*v_pre)(PRE_ARGS);
@@ -78,16 +77,14 @@ static int concat(struct mdoc *, char *,
static int ebool(POST_ARGS);
static int berr_ge1(POST_ARGS);
static int bwarn_ge1(POST_ARGS);
-static int eerr_eq0(POST_ARGS);
-static int eerr_eq1(POST_ARGS);
static int eerr_ge1(POST_ARGS);
-static int eerr_le1(POST_ARGS);
static int ewarn_eq0(POST_ARGS);
+static int ewarn_eq1(POST_ARGS);
static int ewarn_ge1(POST_ARGS);
-static int herr_eq0(POST_ARGS);
-static int herr_ge1(POST_ARGS);
+static int ewarn_le1(POST_ARGS);
static int hwarn_eq0(POST_ARGS);
static int hwarn_eq1(POST_ARGS);
+static int hwarn_ge1(POST_ARGS);
static int hwarn_le1(POST_ARGS);
static int post_an(POST_ARGS);
@@ -138,29 +135,29 @@ static v_post posts_bd[] = { post_literal, hwarn_eq0, bwarn_ge1, NULL };
static v_post posts_bf[] = { hwarn_le1, post_bf, NULL };
static v_post posts_bk[] = { hwarn_eq0, bwarn_ge1, NULL };
static v_post posts_bl[] = { bwarn_ge1, post_bl, NULL };
-static v_post posts_bool[] = { eerr_eq1, ebool, NULL };
+static v_post posts_bool[] = { ebool, NULL };
static v_post posts_eoln[] = { post_eoln, NULL };
static v_post posts_defaults[] = { post_defaults, NULL };
static v_post posts_dd[] = { ewarn_ge1, post_dd, post_prol, NULL };
-static v_post posts_dl[] = { post_literal, bwarn_ge1, herr_eq0, NULL };
+static v_post posts_dl[] = { post_literal, bwarn_ge1, NULL };
static v_post posts_dt[] = { post_dt, post_prol, NULL };
static v_post posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
static v_post posts_it[] = { post_it, NULL };
-static v_post posts_lb[] = { eerr_eq1, post_lb, NULL };
+static v_post posts_lb[] = { post_lb, NULL };
static v_post posts_nd[] = { berr_ge1, NULL };
static v_post posts_nm[] = { post_nm, NULL };
static v_post posts_notext[] = { ewarn_eq0, NULL };
static v_post posts_os[] = { post_os, post_prol, NULL };
-static v_post posts_rs[] = { berr_ge1, herr_eq0, post_rs, NULL };
-static v_post posts_sh[] = { post_ignpar, herr_ge1, bwarn_ge1, post_sh, NULL };
-static v_post posts_sp[] = { eerr_le1, NULL };
-static v_post posts_ss[] = { post_ignpar, herr_ge1, bwarn_ge1, NULL };
-static v_post posts_st[] = { eerr_eq1, post_st, NULL };
+static v_post posts_rs[] = { post_rs, NULL };
+static v_post posts_sh[] = { post_ignpar, hwarn_ge1, bwarn_ge1, post_sh, NULL };
+static v_post posts_sp[] = { ewarn_le1, NULL };
+static v_post posts_ss[] = { post_ignpar, hwarn_ge1, bwarn_ge1, NULL };
+static v_post posts_st[] = { post_st, NULL };
static v_post posts_std[] = { post_std, NULL };
static v_post posts_text[] = { eerr_ge1, NULL };
-static v_post posts_text1[] = { eerr_eq1, NULL };
+static v_post posts_text1[] = { ewarn_eq1, NULL };
static v_post posts_vt[] = { post_vt, NULL };
-static v_post posts_wline[] = { bwarn_ge1, herr_eq0, NULL };
+static v_post posts_wline[] = { bwarn_ge1, NULL };
static v_post posts_wtext[] = { ewarn_ge1, NULL };
static v_pre pres_an[] = { pre_an, NULL };
static v_pre pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL };
@@ -380,6 +377,7 @@ check_count(struct mdoc *m, enum mdoc_type type,
enum check_lvl lvl, enum check_ineq ineq, int val)
{
const char *p;
+ enum mandocerr t;
if (m->last->type != type)
return(1);
@@ -391,7 +389,7 @@ check_count(struct mdoc *m, enum mdoc_type type,
return(1);
break;
case (CHECK_GT):
- p = "greater than ";
+ p = "more than ";
if (m->last->nchild > val)
return(1);
break;
@@ -405,18 +403,10 @@ check_count(struct mdoc *m, enum mdoc_type type,
/* NOTREACHED */
}
- if (CHECK_WARN == lvl) {
- return(mdoc_vmsg(m, MANDOCERR_ARGCOUNT,
- m->last->line, m->last->pos,
- "want %s%d children (have %d)",
- p, val, m->last->nchild));
- }
-
- /* FIXME: THIS IS THE SAME AS THE ABOVE. */
+ t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
- return(mdoc_vmsg(m, MANDOCERR_ARGCOUNT,
- m->last->line, m->last->pos,
- "require %s%d children (have %d)",
+ return(mdoc_vmsg(m, t, m->last->line, m->last->pos,
+ "want %s%d children (have %d)",
p, val, m->last->nchild));
}
@@ -424,7 +414,7 @@ static int
berr_ge1(POST_ARGS)
{
- return(check_count(mdoc, MDOC_BODY, CHECK_FATAL, CHECK_GT, 0));
+ return(check_count(mdoc, MDOC_BODY, CHECK_ERROR, CHECK_GT, 0));
}
static int
@@ -434,27 +424,9 @@ bwarn_ge1(POST_ARGS)
}
static int
-eerr_eq0(POST_ARGS)
-{
- return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_EQ, 0));
-}
-
-static int
-eerr_eq1(POST_ARGS)
-{
- return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_EQ, 1));
-}
-
-static int
eerr_ge1(POST_ARGS)
{
- return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_GT, 0));
-}
-
-static int
-eerr_le1(POST_ARGS)
-{
- return(check_count(mdoc, MDOC_ELEM, CHECK_FATAL, CHECK_LT, 2));
+ return(check_count(mdoc, MDOC_ELEM, CHECK_ERROR, CHECK_GT, 0));
}
static int
@@ -464,21 +436,21 @@ ewarn_eq0(POST_ARGS)
}
static int
-ewarn_ge1(POST_ARGS)
+ewarn_eq1(POST_ARGS)
{
- return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0));
+ return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1));
}
static int
-herr_eq0(POST_ARGS)
+ewarn_ge1(POST_ARGS)
{
- return(check_count(mdoc, MDOC_HEAD, CHECK_FATAL, CHECK_EQ, 0));
+ return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_GT, 0));
}
static int
-herr_ge1(POST_ARGS)
+ewarn_le1(POST_ARGS)
{
- return(check_count(mdoc, MDOC_HEAD, CHECK_FATAL, CHECK_GT, 0));
+ return(check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_LT, 2));
}
static int
@@ -494,6 +466,12 @@ hwarn_eq1(POST_ARGS)
}
static int
+hwarn_ge1(POST_ARGS)
+{
+ return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_GT, 0));
+}
+
+static int
hwarn_le1(POST_ARGS)
{
return(check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_LT, 2));
@@ -1046,6 +1024,8 @@ post_lb(POST_ARGS)
char *buf;
size_t sz;
+ check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
+
assert(mdoc->last->child);
assert(MDOC_TEXT == mdoc->last->child->type);
@@ -1238,8 +1218,10 @@ post_an(POST_ARGS)
struct mdoc_node *np;
np = mdoc->last;
- if (AUTH__NONE != np->norm->An.auth && np->child)
- return(eerr_eq0(mdoc));
+ if (AUTH__NONE != np->norm->An.auth && np->child) {
+ check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 0);
+ return(1);
+ }
/*
* FIXME: make this ewarn and make sure that the front-ends
@@ -1581,8 +1563,12 @@ static int
ebool(struct mdoc *mdoc)
{
- if (NULL == mdoc->last->child)
+ if (NULL == mdoc->last->child) {
+ mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY);
+ mdoc_node_delete(mdoc, mdoc->last);
return(1);
+ }
+ check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1);
assert(MDOC_TEXT == mdoc->last->child->type);
@@ -1631,18 +1617,23 @@ post_root(POST_ARGS)
static int
post_st(POST_ARGS)
{
- const char *p;
+ struct mdoc_node *ch;
+ const char *p;
- assert(MDOC_TEXT == mdoc->last->child->type);
+ if (NULL == (ch = mdoc->last->child)) {
+ mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY);
+ mdoc_node_delete(mdoc, mdoc->last);
+ return(1);
+ }
- p = mdoc_a2st(mdoc->last->child->string);
+ assert(MDOC_TEXT == ch->type);
- if (p == NULL) {
+ if (NULL == (p = mdoc_a2st(ch->string))) {
mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADSTANDARD);
mdoc_node_delete(mdoc, mdoc->last);
} else {
- free(mdoc->last->child->string);
- mdoc->last->child->string = mandoc_strdup(p);
+ free(ch->string);
+ ch->string = mandoc_strdup(p);
}
return(1);
@@ -1654,8 +1645,18 @@ post_rs(POST_ARGS)
struct mdoc_node *nn, *next, *prev;
int i, j;
- if (MDOC_BODY != mdoc->last->type)
+ switch (mdoc->last->type) {
+ case (MDOC_HEAD):
+ check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0);
return(1);
+ case (MDOC_BODY):
+ if (mdoc->last->child)
+ break;
+ check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0);
+ return(1);
+ default:
+ return(1);
+ }
/*
* Make sure only certain types of nodes are allowed within the