[v2,1/4] Added implicit variable scope to each include command to support local variables

Message ID 20180605143051.19274-2-david.fabian@bosson.cz
State RFC
Delegated to: Pablo Neira
Headers show
Series
  • Added support for per-file variable scopes and global variables
Related show

Commit Message

David Fabian June 5, 2018, 2:30 p.m.
---
 include/parser.h   | 10 ++++++++--
 src/libnftables.c  |  2 ++
 src/parser_bison.y | 14 ++++++++++----
 src/rule.c         |  1 +
 src/scanner.l      | 18 +++++++++++++++++-
 5 files changed, 38 insertions(+), 7 deletions(-)

Patch

diff --git a/include/parser.h b/include/parser.h
index ea41ca0..1f3eb5f 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -4,14 +4,14 @@ 
 #include <list.h>
 #include <rule.h> // FIXME
 
-#define MAX_INCLUDE_DEPTH		16
+#define MAX_INCLUDE_DEPTH		64
 #define TABSIZE				8
 
 #define YYLTYPE				struct location
 #define YYLTYPE_IS_TRIVIAL		0
 #define YYENABLE_NLS			0
 
-#define SCOPE_NEST_MAX			3
+#define SCOPE_NEST_MAX			(MAX_INCLUDE_DEPTH + 3)
 
 struct parser_state {
 	struct input_descriptor		*indesc;
@@ -33,6 +33,12 @@  struct mnl_socket;
 
 extern void parser_init(struct nft_ctx *nft, struct parser_state *state,
 			struct list_head *msgs, struct list_head *cmds);
+extern void parser_destroy(struct parser_state *state);
+
+extern void open_scope(struct parser_state *state, struct scope *scope);
+extern void close_scope(struct parser_state *state);
+extern struct scope *current_scope(const struct parser_state *state);
+
 extern int nft_parse(struct nft_ctx *ctx, void *, struct parser_state *state);
 
 extern void *scanner_init(struct parser_state *state);
diff --git a/src/libnftables.c b/src/libnftables.c
index 5bc7ba0..54ad614 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -411,6 +411,7 @@  static int nft_parse_bison_buffer(struct nft_ctx *nft, char *buf, size_t buflen,
 	list_for_each_entry(cmd, cmds, list)
 		nft_cmd_expand(cmd);
 
+	parser_destroy(nft->state);
 	return 0;
 }
 
@@ -433,6 +434,7 @@  static int nft_parse_bison_filename(struct nft_ctx *nft, const char *filename,
 	list_for_each_entry(cmd, cmds, list)
 		nft_cmd_expand(cmd);
 
+	parser_destroy(nft->state);
 	return 0;
 }
 
diff --git a/src/parser_bison.y b/src/parser_bison.y
index d13eaa6..16a1f75 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -51,27 +51,33 @@  void parser_init(struct nft_ctx *nft, struct parser_state *state,
 	state->ectx.octx = &nft->output;
 }
 
+void parser_destroy(struct parser_state *state)
+{
+	scope_release(state->scopes[0]);
+}
+
 static void yyerror(struct location *loc, struct nft_ctx *nft, void *scanner,
 		    struct parser_state *state, const char *s)
 {
 	erec_queue(error(loc, "%s", s), state->msgs);
 }
 
-static struct scope *current_scope(const struct parser_state *state)
+struct scope *current_scope(const struct parser_state *state)
 {
 	return state->scopes[state->scope];
 }
 
-static void open_scope(struct parser_state *state, struct scope *scope)
+void open_scope(struct parser_state *state, struct scope *scope)
 {
 	assert(state->scope < array_size(state->scopes) - 1);
 	scope_init(scope, current_scope(state));
 	state->scopes[++state->scope] = scope;
 }
 
-static void close_scope(struct parser_state *state)
+void close_scope(struct parser_state *state)
 {
 	assert(state->scope > 0);
+	scope_release(state->scopes[state->scope]);
 	state->scope--;
 }
 
@@ -778,6 +784,7 @@  common_block		:	INCLUDE		QUOTED_STRING	stmt_separator
 					erec_queue(error(&@2, "redefinition of symbol '%s'", $2),
 						   state->msgs);
 					xfree($2);
+					expr_free($4);
 					YYERROR;
 				}
 
@@ -840,7 +847,6 @@  line			:	common_block			{ $$ = NULL; }
 				if (state->nerrs)
 					YYABORT;
 				$$ = NULL;
-
 				YYACCEPT;
 			}
 			;
diff --git a/src/rule.c b/src/rule.c
index 3e8dea4..38529af 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -17,6 +17,7 @@ 
 #include <errno.h>
 
 #include <statement.h>
+#include <parser.h>
 #include <rule.h>
 #include <utils.h>
 #include <netdb.h>
diff --git a/src/scanner.l b/src/scanner.l
index 6a861cf..e6e255d 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -629,7 +629,15 @@  addrstring	({macaddr}|{ip4addr}|{ip6addr})
 {comment}
 
 <<EOF>> 		{
-				update_pos(yyget_extra(yyscanner), yylloc, 1);
+				struct parser_state *state = yyget_extra(yyscanner);
+				struct scope *scope = current_scope(state);
+				update_pos(state, yylloc, 1);
+				/* only close scope if file was included, skip buffer parsing
+				   since it does not create new scope */
+				if (state->indesc && state->indesc->name) {
+					close_scope(state);
+					xfree(scope);
+				}
 				scanner_pop_buffer(yyscanner);
 				if (YY_CURRENT_BUFFER == NULL)
 					return TOKEN_EOF;
@@ -644,6 +652,10 @@  static void scanner_pop_buffer(yyscan_t scanner)
 	struct parser_state *state = yyget_extra(scanner);
 
 	yypop_buffer_state(scanner);
+	if (state->indesc && state->indesc->name) {
+		xfree(state->indesc->name);
+		state->indesc->name = NULL;
+	}
 	state->indesc = &state->indescs[--state->indesc_idx - 1];
 }
 
@@ -651,6 +663,7 @@  static struct error_record *scanner_push_file(void *scanner, const char *filenam
 					      FILE *f, const struct location *loc)
 {
 	struct parser_state *state = yyget_extra(scanner);
+	struct scope *scope = NULL;
 	YY_BUFFER_STATE b;
 
 	if (state->indesc_idx == MAX_INCLUDE_DEPTH) {
@@ -668,6 +681,9 @@  static struct error_record *scanner_push_file(void *scanner, const char *filenam
 	state->indesc->type	= INDESC_FILE;
 	state->indesc->name	= xstrdup(filename);
 	init_pos(state);
+	scope = xzalloc(sizeof(*scope));
+	init_list_head(&scope->symbols);
+	open_scope(state, scope);
 	return NULL;
 }