Warn that wildcards must be used as the last character in a string
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 4 Aug 2014 18:10:27 +0000 (14:10 -0400)
committerDavid Goulet <dgoulet@efficios.com>
Tue, 5 Aug 2014 15:42:55 +0000 (11:42 -0400)
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 <jeremie.galarneau@efficios.com>
Signed-off-by: David Goulet <dgoulet@efficios.com>
src/lib/lttng-ctl/filter/Makefile.am
src/lib/lttng-ctl/filter/filter-ast.h
src/lib/lttng-ctl/filter/filter-visitor-ir-validate-string.c [new file with mode: 0644]
src/lib/lttng-ctl/lttng-ctl.c

index 4ff345aa4c3d18097e0965026cac9ea8b5fccf78..71a53c108066b88624444c541a5db4a3a9f14c9d 100644 (file)
@@ -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 \
index 405c6686a4f5fd576e3033a4cfafe7086d2326ce..7f1883f29656ba1836699b11bc3178d02dfe7966 100644 (file)
@@ -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 (file)
index 0000000..34b4b19
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * filter-visitor-ir-validate-string.c
+ *
+ * LTTng filter IR validate string
+ *
+ * Copyright 2014 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#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);
+}
index 536d41baa2bc4848b334405afa598a210dc5422e..b9dc1efb095de163ff3d4ca50bfba28ed6596378 100644 (file)
@@ -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... ");
This page took 0.02815 seconds and 4 git commands to generate.