Filtering: add support for star-only globbing patterns
[lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
index 0caeab6f87f66bcc838fb565dbf097575aea2e6e..afea3f151ff460e5dda5f5beef2908340ab10671 100644 (file)
@@ -27,6 +27,7 @@
 #define _LGPL_SOURCE
 #include <urcu-pointer.h>
 #include "lttng-filter.h"
+#include "string-utils.h"
 
 /*
  * -1: wildcard found.
@@ -54,6 +55,46 @@ int parse_char(const char **p)
        }
 }
 
+/*
+ * Returns -1ULL if the string is null-terminated, or the number of
+ * characters if not.
+ */
+static
+size_t get_str_or_seq_len(const struct estack_entry *entry)
+{
+       if (entry->u.s.seq_len == UINT_MAX) {
+               return -1ULL;
+       } else {
+               return entry->u.s.seq_len;
+       }
+}
+
+static
+int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
+{
+       const char *pattern;
+       const char *candidate;
+       size_t pattern_len;
+       size_t candidate_len;
+
+       /* Find out which side is the pattern vs. the candidate. */
+       if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
+               pattern = estack_ax(stack, top)->u.s.str;
+               pattern_len = get_str_or_seq_len(estack_ax(stack, top));
+               candidate = estack_bx(stack, top)->u.s.str;
+               candidate_len = get_str_or_seq_len(estack_bx(stack, top));
+       } else {
+               pattern = estack_bx(stack, top)->u.s.str;
+               pattern_len = get_str_or_seq_len(estack_bx(stack, top));
+               candidate = estack_ax(stack, top)->u.s.str;
+               candidate_len = get_str_or_seq_len(estack_ax(stack, top));
+       }
+
+       /* Perform the match. Returns 0 when the result is true. */
+       return !strutils_star_glob_match(pattern, pattern_len, candidate,
+               candidate_len);
+}
+
 static
 int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
 {
@@ -68,7 +109,8 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
                        if (q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0') {
                                return 0;
                        } else {
-                               if (estack_ax(stack, top)->u.s.literal) {
+                               if (estack_ax(stack, top)->u.s.literal_type ==
+                                               ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                                        ret = parse_char(&q);
                                        if (ret == -1)
                                                return 0;
@@ -77,14 +119,16 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
                        }
                }
                if (unlikely(q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0')) {
-                       if (estack_bx(stack, top)->u.s.literal) {
+                       if (estack_bx(stack, top)->u.s.literal_type ==
+                                       ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                                ret = parse_char(&p);
                                if (ret == -1)
                                        return 0;
                        }
                        return 1;
                }
-               if (estack_bx(stack, top)->u.s.literal) {
+               if (estack_bx(stack, top)->u.s.literal_type ==
+                               ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                        ret = parse_char(&p);
                        if (ret == -1) {
                                return 0;
@@ -93,7 +137,8 @@ int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
                        }
                        /* else compare both char */
                }
-               if (estack_ax(stack, top)->u.s.literal) {
+               if (estack_ax(stack, top)->u.s.literal_type ==
+                               ESTACK_STRING_LITERAL_TYPE_PLAIN) {
                        ret = parse_char(&q);
                        if (ret == -1) {
                                return 0;
@@ -228,6 +273,10 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
                [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
 
+               /* globbing pattern binary comparator */
+               [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
+               [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
+
                /* s64 binary comparator */
                [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
                [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
@@ -283,6 +332,7 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
 
                /* load from immediate operand */
                [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
+               [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
                [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
                [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
 
@@ -343,7 +393,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_EQ_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_EQ_DOUBLE_S64);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -359,7 +410,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_EQ_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_EQ_DOUBLE);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -377,6 +429,26 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        goto end;
                                case REG_STRING:
                                        JUMP_TO(FILTER_OP_EQ_STRING);
+                               case REG_STAR_GLOB_STRING:
+                                       JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
+                               default:
+                                       ERR("Unknown filter register type (%d)",
+                                               (int) estack_bx_t);
+                                       ret = -EINVAL;
+                                       goto end;
+                               }
+                               break;
+                       case REG_STAR_GLOB_STRING:
+                               switch (estack_bx_t) {
+                               case REG_S64:   /* Fall-through */
+                               case REG_DOUBLE:
+                                       ret = -EINVAL;
+                                       goto end;
+                               case REG_STRING:
+                                       JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
+                               case REG_STAR_GLOB_STRING:
+                                       ret = -EINVAL;
+                                       goto end;
                                default:
                                        ERR("Unknown filter register type (%d)",
                                                (int) estack_bx_t);
@@ -401,7 +473,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_NE_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_NE_DOUBLE_S64);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -417,7 +490,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_NE_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_NE_DOUBLE);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -435,6 +509,26 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        goto end;
                                case REG_STRING:
                                        JUMP_TO(FILTER_OP_NE_STRING);
+                               case REG_STAR_GLOB_STRING:
+                                       JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
+                               default:
+                                       ERR("Unknown filter register type (%d)",
+                                               (int) estack_bx_t);
+                                       ret = -EINVAL;
+                                       goto end;
+                               }
+                               break;
+                       case REG_STAR_GLOB_STRING:
+                               switch (estack_bx_t) {
+                               case REG_S64:   /* Fall-through */
+                               case REG_DOUBLE:
+                                       ret = -EINVAL;
+                                       goto end;
+                               case REG_STRING:
+                                       JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
+                               case REG_STAR_GLOB_STRING:
+                                       ret = -EINVAL;
+                                       goto end;
                                default:
                                        ERR("Unknown filter register type (%d)",
                                                (int) estack_bx_t);
@@ -459,7 +553,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_GT_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GT_DOUBLE_S64);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -475,7 +570,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_GT_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GT_DOUBLE);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -488,7 +584,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
-                               case REG_DOUBLE:
+                               case REG_DOUBLE: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                case REG_STRING:
@@ -517,7 +614,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_LT_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LT_DOUBLE_S64);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -533,7 +631,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_LT_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LT_DOUBLE);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -546,7 +645,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
-                               case REG_DOUBLE:
+                               case REG_DOUBLE: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                case REG_STRING:
@@ -575,7 +675,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_GE_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GE_DOUBLE_S64);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -591,7 +692,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_GE_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_GE_DOUBLE);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -604,7 +706,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
-                               case REG_DOUBLE:
+                               case REG_DOUBLE: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                case REG_STRING:
@@ -633,7 +736,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_LE_S64);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LE_DOUBLE_S64);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -649,7 +753,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        JUMP_TO(FILTER_OP_LE_S64_DOUBLE);
                                case REG_DOUBLE:
                                        JUMP_TO(FILTER_OP_LE_DOUBLE);
-                               case REG_STRING:
+                               case REG_STRING: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                default:
@@ -662,7 +767,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        case REG_STRING:
                                switch (estack_bx_t) {
                                case REG_S64:   /* Fall-through */
-                               case REG_DOUBLE:
+                               case REG_DOUBLE: /* Fall-through */
+                               case REG_STAR_GLOB_STRING:
                                        ret = -EINVAL;
                                        goto end;
                                case REG_STRING:
@@ -749,6 +855,29 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        PO;
                }
 
+               OP(FILTER_OP_EQ_STAR_GLOB_STRING):
+               {
+                       int res;
+
+                       res = (stack_star_glob_match(stack, top, "==") == 0);
+                       estack_pop(stack, top, ax, bx, ax_t, bx_t);
+                       estack_ax_v = res;
+                       estack_ax_t = REG_S64;
+                       next_pc += sizeof(struct binary_op);
+                       PO;
+               }
+               OP(FILTER_OP_NE_STAR_GLOB_STRING):
+               {
+                       int res;
+
+                       res = (stack_star_glob_match(stack, top, "!=") != 0);
+                       estack_pop(stack, top, ax, bx, ax_t, bx_t);
+                       estack_ax_v = res;
+                       estack_ax_t = REG_S64;
+                       next_pc += sizeof(struct binary_op);
+                       PO;
+               }
+
                OP(FILTER_OP_EQ_S64):
                {
                        int res;
@@ -1027,7 +1156,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                JUMP_TO(FILTER_OP_UNARY_PLUS_S64);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE);
-                       case REG_STRING:
+                       case REG_STRING: /* Fall-through */
+                       case REG_STAR_GLOB_STRING:
                                ret = -EINVAL;
                                goto end;
                        default:
@@ -1045,7 +1175,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                JUMP_TO(FILTER_OP_UNARY_MINUS_S64);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE);
-                       case REG_STRING:
+                       case REG_STRING: /* Fall-through */
+                       case REG_STAR_GLOB_STRING:
                                ret = -EINVAL;
                                goto end;
                        default:
@@ -1063,7 +1194,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                JUMP_TO(FILTER_OP_UNARY_NOT_S64);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE);
-                       case REG_STRING:
+                       case REG_STRING: /* Fall-through */
+                       case REG_STAR_GLOB_STRING:
                                ret = -EINVAL;
                                goto end;
                        default:
@@ -1169,7 +1301,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                goto end;
                        }
                        estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        estack_ax_t = REG_STRING;
                        dbg_printf("ref load string %s\n", estack_ax(stack, top)->u.s.str);
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
@@ -1195,7 +1328,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                ret = -EINVAL;
                                goto end;
                        }
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
                        PO;
                }
@@ -1241,12 +1375,28 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                        estack_push(stack, top, ax, bx, ax_t, bx_t);
                        estack_ax(stack, top)->u.s.str = insn->data;
                        estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                       estack_ax(stack, top)->u.s.literal = 1;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_PLAIN;
                        estack_ax_t = REG_STRING;
                        next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
                        PO;
                }
 
+               OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
+               {
+                       struct load_op *insn = (struct load_op *) pc;
+
+                       dbg_printf("load globbing pattern %s\n", insn->data);
+                       estack_push(stack, top, ax, bx, ax_t, bx_t);
+                       estack_ax(stack, top)->u.s.str = insn->data;
+                       estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
+                       estack_ax_t = REG_STAR_GLOB_STRING;
+                       next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
+                       PO;
+               }
+
                OP(FILTER_OP_LOAD_S64):
                {
                        struct load_op *insn = (struct load_op *) pc;
@@ -1283,7 +1433,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                JUMP_TO(FILTER_OP_CAST_NOP);
                        case REG_DOUBLE:
                                JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64);
-                       case REG_STRING:
+                       case REG_STRING: /* Fall-through */
+                       case REG_STAR_GLOB_STRING:
                                ret = -EINVAL;
                                goto end;
                        default:
@@ -1345,7 +1496,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                        goto end;
                                }
                                estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                               estack_ax(stack, top)->u.s.literal = 0;
+                               estack_ax(stack, top)->u.s.literal_type =
+                                       ESTACK_STRING_LITERAL_TYPE_NONE;
                                dbg_printf("ref get context dynamic string %s\n", estack_ax(stack, top)->u.s.str);
                                estack_ax_t = REG_STRING;
                                break;
@@ -1379,7 +1531,8 @@ uint64_t lttng_filter_interpret_bytecode(void *filter_data,
                                goto end;
                        }
                        estack_ax(stack, top)->u.s.seq_len = UINT_MAX;
-                       estack_ax(stack, top)->u.s.literal = 0;
+                       estack_ax(stack, top)->u.s.literal_type =
+                               ESTACK_STRING_LITERAL_TYPE_NONE;
                        estack_ax_t = REG_STRING;
                        dbg_printf("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
                        next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
This page took 0.029575 seconds and 4 git commands to generate.