From dcd5daf2e2acb0745d5e6ff66185147007e8ed53 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Mon, 4 Aug 2014 14:10:27 -0400 Subject: [PATCH] Warn that wildcards must be used as the last character in a string MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Wildcards are currently only supported as the last character in a string literal used in an event filter. This rule is not checked which may confuse users who expect complete wildcard support in filter expressions. An error is now reported and the filter string is treated as invalid. Signed-off-by: Jérémie Galarneau Signed-off-by: David Goulet --- src/lib/lttng-ctl/filter/Makefile.am | 1 + src/lib/lttng-ctl/filter/filter-ast.h | 1 + .../filter-visitor-ir-validate-string.c | 148 ++++++++++++++++++ src/lib/lttng-ctl/lttng-ctl.c | 6 + 4 files changed, 156 insertions(+) create mode 100644 src/lib/lttng-ctl/filter/filter-visitor-ir-validate-string.c diff --git a/src/lib/lttng-ctl/filter/Makefile.am b/src/lib/lttng-ctl/filter/Makefile.am index 4ff345aa4..71a53c108 100644 --- a/src/lib/lttng-ctl/filter/Makefile.am +++ b/src/lib/lttng-ctl/filter/Makefile.am @@ -14,6 +14,7 @@ libfilter_la_SOURCES = filter-lexer.l filter-parser.y \ filter-visitor-xml.c \ filter-visitor-generate-ir.c \ filter-visitor-ir-check-binary-op-nesting.c \ + filter-visitor-ir-validate-string.c \ filter-visitor-generate-bytecode.c \ align.h \ bug.h \ diff --git a/src/lib/lttng-ctl/filter/filter-ast.h b/src/lib/lttng-ctl/filter/filter-ast.h index 405c6686a..7f1883f29 100644 --- a/src/lib/lttng-ctl/filter/filter-ast.h +++ b/src/lib/lttng-ctl/filter/filter-ast.h @@ -186,5 +186,6 @@ int filter_visitor_bytecode_generate(struct filter_parser_ctx *ctx); void filter_bytecode_free(struct filter_parser_ctx *ctx); int filter_visitor_ir_check_binary_op_nesting(struct filter_parser_ctx *ctx); int filter_visitor_ir_check_binary_comparator(struct filter_parser_ctx *ctx); +int filter_visitor_ir_validate_string(struct filter_parser_ctx *ctx); #endif /* _FILTER_AST_H */ diff --git a/src/lib/lttng-ctl/filter/filter-visitor-ir-validate-string.c b/src/lib/lttng-ctl/filter/filter-visitor-ir-validate-string.c new file mode 100644 index 000000000..34b4b194b --- /dev/null +++ b/src/lib/lttng-ctl/filter/filter-visitor-ir-validate-string.c @@ -0,0 +1,148 @@ +/* + * filter-visitor-ir-validate-string.c + * + * LTTng filter IR validate string + * + * Copyright 2014 - Jérémie Galarneau + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License, version 2.1 only, + * as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include "filter-ast.h" +#include "filter-parser.h" +#include "filter-ir.h" + +enum parse_char_result { + PARSE_CHAR_UNKNOWN = -2, + PARSE_CHAR_WILDCARD = -1, + PARSE_CHAR_NORMAL = 0, +}; + +static +enum parse_char_result parse_char(const char **p) +{ + switch (**p) { + case '\\': + (*p)++; + switch (**p) { + case '\\': + case '*': + return PARSE_CHAR_NORMAL; + default: + return PARSE_CHAR_UNKNOWN; + } + case '*': + return PARSE_CHAR_WILDCARD; + default: + return PARSE_CHAR_NORMAL; + } +} + +static +int validate_string(struct ir_op *node) +{ + switch (node->op) { + case IR_OP_UNKNOWN: + default: + fprintf(stderr, "[error] %s: unknown op type\n", __func__); + return -EINVAL; + + case IR_OP_ROOT: + return validate_string(node->u.root.child); + case IR_OP_LOAD: + { + int ret = 0; + + if (node->data_type == IR_DATA_STRING) { + const char *str; + + assert(node->u.load.u.string); + str = node->u.load.u.string; + + /* + * Make sure that if a non-escaped wildcard is + * present, it is the last character of the string. + */ + for (;;) { + enum parse_char_result res; + + if (!(*str)) { + break; + } + + res = parse_char(&str); + str++; + + switch (res) { + case PARSE_CHAR_WILDCARD: + { + if (*str) { + /* + * Found a wildcard followed by non-null + * character; unsupported. + */ + ret = -EINVAL; + fprintf(stderr, + "Wildcards may only be used as the last character of a string in a filter.\n"); + goto end_load; + } + break; + } + case PARSE_CHAR_UNKNOWN: + ret = -EINVAL; + fprintf(stderr, + "Unsupported escape character detected.\n"); + goto end_load; + case PARSE_CHAR_NORMAL: + default: + break; + } + } + } +end_load: + return ret; + } + case IR_OP_UNARY: + return validate_string(node->u.unary.child); + case IR_OP_BINARY: + { + int ret = validate_string(node->u.binary.left); + + if (ret) + return ret; + return validate_string(node->u.binary.right); + } + case IR_OP_LOGICAL: + { + int ret; + + ret = validate_string(node->u.logical.left); + if (ret) + return ret; + return validate_string(node->u.logical.right); + } + } +} + +int filter_visitor_ir_validate_string(struct filter_parser_ctx *ctx) +{ + return validate_string(ctx->ir_root); +} diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 536d41baa..b9dc1efb0 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -825,6 +825,12 @@ static int generate_filter(char *filter_expression, ret = -LTTNG_ERR_FILTER_INVAL; goto parse_error; } + /* Validate strings used as literals in the expression */ + ret = filter_visitor_ir_validate_string(ctx); + if (ret) { + ret = -LTTNG_ERR_FILTER_INVAL; + goto parse_error; + } dbg_printf("done\n"); dbg_printf("Generating bytecode... "); -- 2.34.1