bytecode: allow interpreter to return any type
[lttng-ust.git] / liblttng-ust / lttng-filter-validator.c
index 92455c80a554766830dda045ccd5f73d76dc5b09..e6982369bdc1d8c8e90c4c9d8ff29c6f9b20c16a 100644 (file)
  */
 
 #define _LGPL_SOURCE
-#include <urcu-bp.h>
+#include <stddef.h>
+#include <stdint.h>
 #include <time.h>
-#include "lttng-filter.h"
 
+#include <urcu-bp.h>
 #include <urcu/rculfhash.h>
+
+#include "lttng-filter.h"
 #include "lttng-hash-helper.h"
 #include "string-utils.h"
+#include "ust-events-internal.h"
 
 /*
  * Number of merge points for hash table size. Hash table initialized to
@@ -156,6 +160,7 @@ int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode,
                        }
                        break;
                case REG_S64:
+               case REG_U64:
                case REG_DOUBLE:
                        goto error_mismatch;
                }
@@ -174,11 +179,13 @@ int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode,
                        break;
                case REG_STAR_GLOB_STRING:
                case REG_S64:
+               case REG_U64:
                case REG_DOUBLE:
                        goto error_mismatch;
                }
                break;
        case REG_S64:
+       case REG_U64:
        case REG_DOUBLE:
                switch (vstack_bx(stack)->type) {
                default:
@@ -190,6 +197,7 @@ int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode,
                case REG_STAR_GLOB_STRING:
                        goto error_mismatch;
                case REG_S64:
+               case REG_U64:
                case REG_DOUBLE:
                        break;
                }
@@ -232,6 +240,7 @@ int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode,
        case REG_UNKNOWN:
                goto unknown;
        case REG_S64:
+       case REG_U64:
                switch (vstack_bx(stack)->type) {
                default:
                        goto error_type;
@@ -239,6 +248,7 @@ int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode,
                case REG_UNKNOWN:
                        goto unknown;
                case REG_S64:
+               case REG_U64:
                        break;
                }
                break;
@@ -507,6 +517,7 @@ int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
                if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_symbol)
                                > start_pc + bytecode->len)) {
                        ret = -ERANGE;
+                       break;
                }
                ret = validate_get_symbol(bytecode, sym);
                break;
@@ -690,8 +701,20 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        ret = -EINVAL;
                        goto end;
                }
-               if (vstack_ax(stack)->type != REG_S64
-                               || vstack_bx(stack)->type != REG_S64) {
+               switch (vstack_ax(stack)->type) {
+               case REG_S64:
+               case REG_U64:
+                       break;
+               default:
+                       ERR("Unexpected register type for s64 comparator\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               switch (vstack_bx(stack)->type) {
+               case REG_S64:
+               case REG_U64:
+                       break;
+               default:
                        ERR("Unexpected register type for s64 comparator\n");
                        ret = -EINVAL;
                        goto end;
@@ -731,7 +754,19 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        ret = -EINVAL;
                        goto end;
                }
-               if (vstack_ax(stack)->type != REG_S64 && vstack_bx(stack)->type != REG_DOUBLE) {
+               switch (vstack_ax(stack)->type) {
+               case REG_S64:
+               case REG_U64:
+                       break;
+               default:
+                       ERR("Double-S64 operator has unexpected register types\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               switch (vstack_bx(stack)->type) {
+               case REG_DOUBLE:
+                       break;
+               default:
                        ERR("Double-S64 operator has unexpected register types\n");
                        ret = -EINVAL;
                        goto end;
@@ -751,7 +786,19 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        ret = -EINVAL;
                        goto end;
                }
-               if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_S64) {
+               switch (vstack_ax(stack)->type) {
+               case REG_DOUBLE:
+                       break;
+               default:
+                       ERR("S64-Double operator has unexpected register types\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               switch (vstack_bx(stack)->type) {
+               case REG_S64:
+               case REG_U64:
+                       break;
+               default:
                        ERR("S64-Double operator has unexpected register types\n");
                        ret = -EINVAL;
                        goto end;
@@ -808,6 +855,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        goto end;
                case REG_S64:
                        break;
+               case REG_U64:
+                       break;
                case REG_DOUBLE:
                        break;
                case REG_UNKNOWN:
@@ -836,6 +885,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        goto end;
                case REG_S64:
                        break;
+               case REG_U64:
+                       break;
                case REG_UNKNOWN:
                        break;
                }
@@ -851,7 +902,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        ret = -EINVAL;
                        goto end;
                }
-               if (vstack_ax(stack)->type != REG_S64) {
+               if (vstack_ax(stack)->type != REG_S64 &&
+                               vstack_ax(stack)->type != REG_U64) {
                        ERR("Invalid register type\n");
                        ret = -EINVAL;
                        goto end;
@@ -888,8 +940,9 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        goto end;
                }
                if (vstack_ax(stack)->type != REG_S64
+                               && vstack_ax(stack)->type != REG_U64
                                && vstack_ax(stack)->type != REG_UNKNOWN) {
-                       ERR("Logical comparator expects S64 or dynamic register\n");
+                       ERR("Logical comparator expects S64, U64 or dynamic register\n");
                        ret = -EINVAL;
                        goto end;
                }
@@ -980,6 +1033,8 @@ int validate_instruction_context(struct bytecode_runtime *bytecode,
                        goto end;
                case REG_S64:
                        break;
+               case REG_U64:
+                       break;
                case REG_DOUBLE:
                        break;
                case REG_UNKNOWN:
@@ -1245,6 +1300,10 @@ int exec_insn(struct bytecode_runtime *bytecode,
                }
                switch (vstack_ax(stack)->type) {
                case REG_S64:
+               case REG_U64:
+               case REG_DOUBLE:
+               case REG_STRING:
+               case REG_PTR:
                case REG_UNKNOWN:
                        break;
                default:
@@ -1266,6 +1325,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                }
                switch (vstack_ax(stack)->type) {
                case REG_S64:
+               case REG_U64:
                        break;
                default:
                case REG_UNKNOWN:
@@ -1330,6 +1390,37 @@ int exec_insn(struct bytecode_runtime *bytecode,
        case FILTER_OP_LT_S64_DOUBLE:
        case FILTER_OP_GE_S64_DOUBLE:
        case FILTER_OP_LE_S64_DOUBLE:
+       {
+               /* Pop 2, push 1 */
+               if (vstack_pop(stack)) {
+                       ret = -EINVAL;
+                       goto end;
+               }
+               if (!vstack_ax(stack)) {
+                       ERR("Empty stack\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               switch (vstack_ax(stack)->type) {
+               case REG_S64:
+               case REG_U64:
+               case REG_DOUBLE:
+               case REG_STRING:
+               case REG_STAR_GLOB_STRING:
+               case REG_UNKNOWN:
+                       break;
+               default:
+                       ERR("Unexpected register type %d for operation\n",
+                               (int) vstack_ax(stack)->type);
+                       ret = -EINVAL;
+                       goto end;
+               }
+
+               vstack_ax(stack)->type = REG_S64;
+               next_pc += sizeof(struct binary_op);
+               break;
+       }
+
        case FILTER_OP_BIT_RSHIFT:
        case FILTER_OP_BIT_LSHIFT:
        case FILTER_OP_BIT_AND:
@@ -1348,6 +1439,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                }
                switch (vstack_ax(stack)->type) {
                case REG_S64:
+               case REG_U64:
                case REG_DOUBLE:
                case REG_STRING:
                case REG_STAR_GLOB_STRING:
@@ -1360,7 +1452,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                        goto end;
                }
 
-               vstack_ax(stack)->type = REG_S64;
+               vstack_ax(stack)->type = REG_U64;
                next_pc += sizeof(struct binary_op);
                break;
        }
@@ -1379,6 +1471,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                case REG_UNKNOWN:
                case REG_DOUBLE:
                case REG_S64:
+               case REG_U64:
                        break;
                default:
                        ERR("Unexpected register type %d for operation\n",
@@ -1403,6 +1496,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                }
                switch (vstack_ax(stack)->type) {
                case REG_S64:
+               case REG_U64:
                        break;
                default:
                        ERR("Unexpected register type %d for operation\n",
@@ -1411,7 +1505,6 @@ int exec_insn(struct bytecode_runtime *bytecode,
                        goto end;
                }
 
-               vstack_ax(stack)->type = REG_S64;
                next_pc += sizeof(struct unary_op);
                break;
        }
@@ -1428,6 +1521,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                case REG_UNKNOWN:
                case REG_DOUBLE:
                case REG_S64:
+               case REG_U64:
                        break;
                default:
                        ERR("Unexpected register type %d for operation\n",
@@ -1436,7 +1530,6 @@ int exec_insn(struct bytecode_runtime *bytecode,
                        goto end;
                }
 
-               vstack_ax(stack)->type = REG_S64;
                next_pc += sizeof(struct unary_op);
                break;
        }
@@ -1452,6 +1545,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                switch (vstack_ax(stack)->type) {
                case REG_UNKNOWN:
                case REG_S64:
+               case REG_U64:
                        break;
                case REG_DOUBLE:
                default:
@@ -1461,7 +1555,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                        goto end;
                }
 
-               vstack_ax(stack)->type = REG_S64;
+               vstack_ax(stack)->type = REG_U64;
                next_pc += sizeof(struct unary_op);
                break;
        }
@@ -1536,6 +1630,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                /* There is always a cast-to-s64 operation before a or/and op. */
                switch (vstack_ax(stack)->type) {
                case REG_S64:
+               case REG_U64:
                        break;
                default:
                        ERR("Incorrect register type %d for operation\n",
@@ -1669,6 +1764,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                }
                switch (vstack_ax(stack)->type) {
                case REG_S64:
+               case REG_U64:
                case REG_DOUBLE:
                case REG_UNKNOWN:
                        break;
@@ -1726,6 +1822,23 @@ int exec_insn(struct bytecode_runtime *bytecode,
        case FILTER_OP_LOAD_FIELD_S16:
        case FILTER_OP_LOAD_FIELD_S32:
        case FILTER_OP_LOAD_FIELD_S64:
+       {
+               /* Pop 1, push 1 */
+               if (!vstack_ax(stack)) {
+                       ERR("Empty stack\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               if (vstack_ax(stack)->type != REG_PTR) {
+                       ERR("Expecting pointer on top of stack\n");
+                       ret = -EINVAL;
+                       goto end;
+               }
+               vstack_ax(stack)->type = REG_S64;
+               next_pc += sizeof(struct load_op);
+               break;
+       }
+
        case FILTER_OP_LOAD_FIELD_U8:
        case FILTER_OP_LOAD_FIELD_U16:
        case FILTER_OP_LOAD_FIELD_U32:
@@ -1742,7 +1855,7 @@ int exec_insn(struct bytecode_runtime *bytecode,
                        ret = -EINVAL;
                        goto end;
                }
-               vstack_ax(stack)->type = REG_S64;
+               vstack_ax(stack)->type = REG_U64;
                next_pc += sizeof(struct load_op);
                break;
        }
This page took 0.027504 seconds and 4 git commands to generate.