- goto end;
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_LT:
- {
- ret = bin_op_compare_check(reg, "<");
- if (ret)
- goto end;
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_GE:
- {
- ret = bin_op_compare_check(reg, ">=");
- if (ret)
- goto end;
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_LE:
- {
- ret = bin_op_compare_check(reg, "<=");
- if (ret)
- goto end;
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
-
- case FILTER_OP_EQ_STRING:
- case FILTER_OP_NE_STRING:
- case FILTER_OP_GT_STRING:
- case FILTER_OP_LT_STRING:
- case FILTER_OP_GE_STRING:
- case FILTER_OP_LE_STRING:
- {
- if (reg[REG_R0].type != REG_STRING
- || reg[REG_R1].type != REG_STRING) {
- ERR("Unexpected register type for string comparator\n");
- ret = -EINVAL;
- goto end;
- }
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
-
- case FILTER_OP_EQ_S64:
- case FILTER_OP_NE_S64:
- case FILTER_OP_GT_S64:
- case FILTER_OP_LT_S64:
- case FILTER_OP_GE_S64:
- case FILTER_OP_LE_S64:
- {
- if (reg[REG_R0].type != REG_S64
- || reg[REG_R1].type != REG_S64) {
- ERR("Unexpected register type for s64 comparator\n");
- ret = -EINVAL;
- goto end;
- }
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
-
- case FILTER_OP_EQ_DOUBLE:
- case FILTER_OP_NE_DOUBLE:
- case FILTER_OP_GT_DOUBLE:
- case FILTER_OP_LT_DOUBLE:
- case FILTER_OP_GE_DOUBLE:
- case FILTER_OP_LE_DOUBLE:
- {
- if ((reg[REG_R0].type != REG_DOUBLE && reg[REG_R0].type != REG_S64)
- || (reg[REG_R1].type != REG_DOUBLE && reg[REG_R1].type != REG_S64)) {
- ERR("Unexpected register type for double comparator\n");
- ret = -EINVAL;
- goto end;
- }
- reg[REG_R0].type = REG_DOUBLE;
- next_pc += sizeof(struct binary_op);
- break;
- }
-
- /* unary */
- case FILTER_OP_UNARY_PLUS:
- case FILTER_OP_UNARY_MINUS:
- case FILTER_OP_UNARY_NOT:
- {
- struct unary_op *insn = (struct unary_op *) pc;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- switch (reg[insn->reg].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_STRING:
- ERR("Unary op can only be applied to numeric or floating point registers\n");
- ret = -EINVAL;
- goto end;
- case REG_S64:
- break;
- case REG_DOUBLE:
- break;
- }
- next_pc += sizeof(struct unary_op);
- break;
- }
-
- case FILTER_OP_UNARY_PLUS_S64:
- case FILTER_OP_UNARY_MINUS_S64:
- case FILTER_OP_UNARY_NOT_S64:
- {
- struct unary_op *insn = (struct unary_op *) pc;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- if (reg[insn->reg].type != REG_S64) {
- ERR("Invalid register type\n");
- ret = -EINVAL;
- goto end;
- }
- next_pc += sizeof(struct unary_op);
- break;
- }
-
- case FILTER_OP_UNARY_PLUS_DOUBLE:
- case FILTER_OP_UNARY_MINUS_DOUBLE:
- case FILTER_OP_UNARY_NOT_DOUBLE:
- {
- struct unary_op *insn = (struct unary_op *) pc;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- if (reg[insn->reg].type != REG_DOUBLE) {
- ERR("Invalid register type\n");
- ret = -EINVAL;
- goto end;
- }
- next_pc += sizeof(struct unary_op);
- break;
- }
-
- /* logical */
- case FILTER_OP_AND:
- case FILTER_OP_OR:
- {
- struct logical_op *insn = (struct logical_op *) pc;
-
- if (unlikely(reg[REG_R0].type == REG_TYPE_UNKNOWN
- || reg[REG_R0].type == REG_TYPE_UNKNOWN
- || reg[REG_R0].type == REG_STRING
- || reg[REG_R1].type == REG_STRING)) {
- ERR("Logical comparator can only be applied to numeric and floating point registers\n");
- ret = -EINVAL;
- goto end;
- }
-
- dbg_printf("Validate jumping to bytecode offset %u\n",
- (unsigned int) insn->skip_offset);
- if (unlikely(start_pc + insn->skip_offset <= pc)) {
- ERR("Loops are not allowed in bytecode\n");
- ret = -EINVAL;
- goto end;
- }
- next_pc += sizeof(struct logical_op);
- break;
- }
-
- /* load */
- case FILTER_OP_LOAD_FIELD_REF:
- {
- ERR("Unknown field ref type\n");
- ret = -EINVAL;
- goto end;
- }
- case FILTER_OP_LOAD_FIELD_REF_STRING:
- case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
- {
- struct load_op *insn = (struct load_op *) pc;
- struct field_ref *ref = (struct field_ref *) insn->data;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- dbg_printf("Validate load field ref offset %u type string\n",
- ref->offset);
- reg[insn->reg].type = REG_STRING;
- reg[insn->reg].literal = 0;
- next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
- break;
- }
- case FILTER_OP_LOAD_FIELD_REF_S64:
- {
- struct load_op *insn = (struct load_op *) pc;
- struct field_ref *ref = (struct field_ref *) insn->data;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- dbg_printf("Validate load field ref offset %u type s64\n",
- ref->offset);
- reg[insn->reg].type = REG_S64;
- reg[insn->reg].literal = 0;
- next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
- break;
- }
- case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
- {
- struct load_op *insn = (struct load_op *) pc;
- struct field_ref *ref = (struct field_ref *) insn->data;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- dbg_printf("Validate load field ref offset %u type double\n",
- ref->offset);
- reg[insn->reg].type = REG_DOUBLE;
- reg[insn->reg].literal = 0;
- next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
- break;
- }
-
- case FILTER_OP_LOAD_STRING:
- {
- struct load_op *insn = (struct load_op *) pc;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- reg[insn->reg].type = REG_STRING;
- reg[insn->reg].literal = 1;
- next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
- break;
- }
-
- case FILTER_OP_LOAD_S64:
- {
- struct load_op *insn = (struct load_op *) pc;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- reg[insn->reg].type = REG_S64;
- reg[insn->reg].literal = 1;
- next_pc += sizeof(struct load_op)
- + sizeof(struct literal_numeric);
- break;
- }
-
- case FILTER_OP_LOAD_DOUBLE:
- {
- struct load_op *insn = (struct load_op *) pc;
-
- if (unlikely(insn->reg >= REG_ERROR)) {
- ERR("invalid register %u\n",
- (unsigned int) insn->reg);
- ret = -EINVAL;
- goto end;
- }
- reg[insn->reg].type = REG_DOUBLE;
- reg[insn->reg].literal = 1;
- next_pc += sizeof(struct load_op)
- + sizeof(struct literal_double);
- break;
- }