aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Gritton <jamie@FreeBSD.org>2023-06-04 03:07:09 +0000
committerJamie Gritton <jamie@FreeBSD.org>2023-06-04 03:07:09 +0000
commit086e0149ae56641af245ce472e787c2f67d3aea5 (patch)
treeb8878f5878da7e40a8117a6d2f45c9b89bce40dd
parent097db30a8e0310ac28075787fb92ea40dad8b27b (diff)
downloadsrc-086e0149ae56641af245ce472e787c2f67d3aea5.tar.gz
src-086e0149ae56641af245ce472e787c2f67d3aea5.zip
jail: Use re-entrant versions of lex & yacc, and lex's yylineno
-rw-r--r--usr.sbin/jail/config.c27
-rw-r--r--usr.sbin/jail/jail.c8
-rw-r--r--usr.sbin/jail/jaillex.l76
-rw-r--r--usr.sbin/jail/jailp.h11
-rw-r--r--usr.sbin/jail/jailparse.y27
5 files changed, 83 insertions, 66 deletions
diff --git a/usr.sbin/jail/config.c b/usr.sbin/jail/config.c
index cbf5859b1329..52e1cbf05c28 100644
--- a/usr.sbin/jail/config.c
+++ b/usr.sbin/jail/config.c
@@ -51,10 +51,10 @@ struct ipspec {
unsigned flags;
};
-extern FILE *yyin;
-extern int yynerrs;
-
-extern int yyparse(void);
+extern int yylex_init_extra(struct cflex *extra, void *scanner);
+extern int yylex_destroy(void *scanner);
+extern int yyparse(void *scanner);
+extern int yyset_in(FILE *fp, void *scanner);
struct cfjails cfjails = TAILQ_HEAD_INITIALIZER(cfjails);
@@ -127,7 +127,7 @@ static const struct ipspec intparams[] = {
* Parse the jail configuration file.
*/
void
-load_config(void)
+load_config(const char *cfname)
{
struct cfjails wild;
struct cfparams opp;
@@ -135,19 +135,26 @@ load_config(void)
struct cfparam *p, *vp, *tp;
struct cfstring *s, *vs, *ns;
struct cfvar *v, *vv;
+ struct cflex cflex;
char *ep;
+ void *scanner;
int did_self, jseq, pgen;
+ cflex.cfname = cfname;
+ cflex.error = 0;
+ yylex_init_extra(&cflex, &scanner);
if (!strcmp(cfname, "-")) {
- cfname = "STDIN";
- yyin = stdin;
+ cflex.cfname = "STDIN";
+ yyset_in(stdin, scanner);
} else {
- yyin = fopen(cfname, "r");
- if (!yyin)
+ FILE *yfp = fopen(cfname, "r");
+ if (!yfp)
err(1, "%s", cfname);
+ yyset_in(yfp, scanner);
}
- if (yyparse() || yynerrs)
+ if (yyparse(scanner) || cflex.error)
exit(1);
+ yylex_destroy(scanner);
/* Separate the wildcard jails out from the actual jails. */
jseq = 0;
diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c
index 02eb957a2d45..a2c725d51b70 100644
--- a/usr.sbin/jail/jail.c
+++ b/usr.sbin/jail/jail.c
@@ -56,7 +56,6 @@ struct permspec {
int rev;
};
-const char *cfname;
int iflag;
int note_remove;
int verbose;
@@ -138,6 +137,7 @@ main(int argc, char **argv)
FILE *jfp;
struct cfjail *j;
char *JidFile;
+ const char *cfname;
size_t sysvallen;
unsigned op, pi;
int ch, docf, error, i, oldcl, sysval;
@@ -287,7 +287,7 @@ main(int argc, char **argv)
} else if (op == JF_STOP || op == JF_SHOW) {
/* Just print list of all configured non-wildcard jails */
if (op == JF_SHOW) {
- load_config();
+ load_config(cfname);
show_jails();
exit(0);
}
@@ -300,7 +300,7 @@ main(int argc, char **argv)
usage();
if ((docf = !Rflag &&
(!strcmp(cfname, "-") || stat(cfname, &st) == 0)))
- load_config();
+ load_config(cfname);
note_remove = docf || argc > 1 || wild_jail_name(argv[0]);
} else if (argc > 1 || (argc == 1 && strchr(argv[0], '='))) {
/* Single jail specified on the command line */
@@ -348,7 +348,7 @@ main(int argc, char **argv)
/* From the config file, perhaps with a specified jail */
if (Rflag || !docf)
usage();
- load_config();
+ load_config(cfname);
}
/* Find out which jails will be run. */
diff --git a/usr.sbin/jail/jaillex.l b/usr.sbin/jail/jaillex.l
index 1dcf5bef5358..540b43ab3c5c 100644
--- a/usr.sbin/jail/jaillex.l
+++ b/usr.sbin/jail/jaillex.l
@@ -38,40 +38,32 @@ __FBSDID("$FreeBSD$");
#include "jailp.h"
#include "y.tab.h"
-extern int yynerrs;
+#define YY_DECL int yylex(YYSTYPE *yylval, yyscan_t yyscanner)
+#define YY_EXTRA_TYPE struct cflex*
-static ssize_t text2lval(size_t triml, size_t trimr, int tovar);
+extern YY_DECL;
-static int instr;
-static int lineno = 1;
+static ssize_t text2lval(size_t triml, size_t trimr, int tovar,
+ YYSTYPE *yylval, yyscan_t scanner);
-#define YY_DECL int yylex(void)
+static int instr;
%}
%option noyywrap
%option noinput
%option nounput
+%option reentrant
+%option yylineno
%start _ DQ
%%
/* Whitespace or equivalent */
-<_>[ \t]+ instr = 0;
-<_>#.* ;
-<_>\/\/.* ;
-<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ {
- const char *s;
-
- for (s = yytext; s < yytext + yyleng; s++)
- if (*s == '\n')
- lineno++;
- instr = 0;
- }
-<_>\n {
- lineno++;
- instr = 0;
- }
+<_>[ \t\r\n]+ instr = 0;
+<_>#.* instr = 0;
+<_>\/\/.* instr = 0;
+<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ instr = 0;
/* Reserved tokens */
<_>\+= {
@@ -87,13 +79,13 @@ static int lineno = 1;
<_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ |
<_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) |
<_,DQ>[$*+/\\] {
- (void)text2lval(0, 0, 0);
+ (void)text2lval(0, 0, 0, yylval, yyscanner);
return instr ? STR1 : (instr = 1, STR);
}
/* Single and double quoted strings */
<_>'([^\'\\]|\\(.|\n))*' {
- (void)text2lval(1, 1, 0);
+ (void)text2lval(1, 1, 0, yylval, yyscanner);
return instr ? STR1 : (instr = 1, STR);
}
<_>\"([^"\\]|\\(.|\n))*\" |
@@ -102,7 +94,8 @@ static int lineno = 1;
ssize_t atvar;
skip = yytext[0] == '"' ? 1 : 0;
- atvar = text2lval(skip, 1, 1);
+ atvar = text2lval(skip, 1, 1, yylval,
+ yyscanner);
if (atvar < 0)
BEGIN _;
else {
@@ -120,32 +113,32 @@ static int lineno = 1;
/* Variables, single-word or bracketed */
<_,DQ>$[A-Za-z_][A-Za-z_0-9]* {
- (void)text2lval(1, 0, 0);
+ (void)text2lval(1, 0, 0, yylval, yyscanner);
return instr ? VAR1 : (instr = 1, VAR);
}
<_>$\{([^\n{}]|\\(.|\n))*\} |
<DQ>$\{([^\n\"{}]|\\(.|\n))*\} {
- (void)text2lval(2, 1, 0);
+ (void)text2lval(2, 1, 0, yylval, yyscanner);
return instr ? VAR1 : (instr = 1, VAR);
}
/* Partially formed bits worth complaining about */
<_>\/\*([^*]|(\*+([^*\/])))*\** {
warnx("%s line %d: unterminated comment",
- cfname, lineno);
- yynerrs++;
+ yyextra->cfname, yylineno);
+ yyextra->error = 1;
}
<_>'([^\n'\\]|\\.)* |
<_>\"([^\n\"\\]|\\.)* {
warnx("%s line %d: unterminated string",
- cfname, lineno);
- yynerrs++;
+ yyextra->cfname, yylineno);
+ yyextra->error = 1;
}
<_>$\{([^\n{}]|\\.)* |
<DQ>$\{([^\n\"{}]|\\.)* {
warnx("%s line %d: unterminated variable",
- cfname, lineno);
- yynerrs++;
+ yyextra->cfname, yylineno);
+ yyextra->error = 1;
}
/* A hack because "<0>" rules aren't allowed */
@@ -157,28 +150,19 @@ static int lineno = 1;
%%
-void
-yyerror(const char *s)
-{
- if (!yytext)
- warnx("%s line %d: %s", cfname, lineno, s);
- else if (!yytext[0])
- warnx("%s: unexpected EOF", cfname);
- else
- warnx("%s line %d: %s: %s", cfname, lineno, yytext, s);
-}
-
/*
* Copy string from yytext to yylval, handling backslash escapes,
* and optionally stopping at the beginning of a variable.
*/
static ssize_t
-text2lval(size_t triml, size_t trimr, int tovar)
+text2lval(size_t triml, size_t trimr, int tovar, YYSTYPE *yylval,
+ yyscan_t scanner)
{
char *d;
const char *s, *se;
- yylval.cs = d = emalloc(yyleng - trimr - triml + 1);
+ struct yyguts_t *yyg = scanner;
+ yylval->cs = d = emalloc(yyleng - trimr - triml + 1);
se = yytext + (yyleng - trimr);
for (s = yytext + triml; s < se; s++, d++) {
if (*s != '\\') {
@@ -186,8 +170,6 @@ text2lval(size_t triml, size_t trimr, int tovar)
*d = '\0';
return s - yytext;
}
- if (*s == '\n')
- lineno++;
*d = *s;
continue;
}
@@ -209,8 +191,8 @@ text2lval(size_t triml, size_t trimr, int tovar)
case 'r': *d = '\r'; break;
case 't': *d = '\t'; break;
case 'v': *d = '\v'; break;
- case '\n': d--; lineno++; break;
default: *d = *s; break;
+ case '\n': d--; break;
case 'x':
*d = 0;
if (s + 1 >= se)
diff --git a/usr.sbin/jail/jailp.h b/usr.sbin/jail/jailp.h
index 0325c2a101a4..6ea4e3ec09a3 100644
--- a/usr.sbin/jail/jailp.h
+++ b/usr.sbin/jail/jailp.h
@@ -197,6 +197,11 @@ struct cfdepend {
unsigned flags;
};
+struct cflex {
+ const char *cfname;
+ int error;
+};
+
extern void *emalloc(size_t);
extern void *erealloc(void *, size_t);
extern char *estrdup(const char *);
@@ -209,7 +214,7 @@ extern int next_command(struct cfjail *j);
extern int finish_command(struct cfjail *j);
extern struct cfjail *next_proc(int nonblock);
-extern void load_config(void);
+extern void load_config(const char *cfname);
extern struct cfjail *add_jail(void);
extern void add_param(struct cfjail *j, const struct cfparam *p,
enum intparam ipnum, const char *value);
@@ -232,13 +237,9 @@ extern int start_state(const char *target, int docf, unsigned state,
extern void requeue(struct cfjail *j, struct cfjails *queue);
extern void requeue_head(struct cfjail *j, struct cfjails *queue);
-extern void yyerror(const char *);
-extern int yylex(void);
-
extern struct cfjails cfjails;
extern struct cfjails ready;
extern struct cfjails depend;
-extern const char *cfname;
extern int iflag;
extern int note_remove;
extern int paralimit;
diff --git a/usr.sbin/jail/jailparse.y b/usr.sbin/jail/jailparse.y
index 44e2aacb457e..ccc311a76223 100644
--- a/usr.sbin/jail/jailparse.y
+++ b/usr.sbin/jail/jailparse.y
@@ -30,6 +30,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <err.h>
#include <stdlib.h>
#include <string.h>
@@ -57,6 +58,11 @@ static struct cfjail *global_jail;
%type <ss> value
%type <s> string
+%pure-parser
+
+%lex-param { void *scanner }
+%parse-param { void *scanner }
+
%%
/*
@@ -221,3 +227,24 @@ string : STR
;
%%
+
+extern int YYLEX_DECL();
+
+extern struct cflex *yyget_extra(void *scanner);
+extern int yyget_lineno(void *scanner);
+extern char *yyget_text(void *scanner);
+
+static void
+YYERROR_DECL()
+{
+ if (!yyget_text(scanner))
+ warnx("%s line %d: %s",
+ yyget_extra(scanner)->cfname, yyget_lineno(scanner), s);
+ else if (!yyget_text(scanner)[0])
+ warnx("%s: unexpected EOF",
+ yyget_extra(scanner)->cfname);
+ else
+ warnx("%s line %d: %s: %s",
+ yyget_extra(scanner)->cfname, yyget_lineno(scanner),
+ yyget_text(scanner), s);
+}