{
if (unlikely(pc + sizeof(struct return_op)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
case FILTER_OP_LT_DOUBLE:
case FILTER_OP_GE_DOUBLE:
case FILTER_OP_LE_DOUBLE:
+ case FILTER_OP_EQ_DOUBLE_S64:
+ case FILTER_OP_NE_DOUBLE_S64:
+ case FILTER_OP_GT_DOUBLE_S64:
+ case FILTER_OP_LT_DOUBLE_S64:
+ case FILTER_OP_GE_DOUBLE_S64:
+ case FILTER_OP_LE_DOUBLE_S64:
+ case FILTER_OP_EQ_S64_DOUBLE:
+ case FILTER_OP_NE_S64_DOUBLE:
+ case FILTER_OP_GT_S64_DOUBLE:
+ case FILTER_OP_LT_S64_DOUBLE:
+ case FILTER_OP_GE_S64_DOUBLE:
+ case FILTER_OP_LE_S64_DOUBLE:
{
if (unlikely(pc + sizeof(struct binary_op)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
{
if (unlikely(pc + sizeof(struct unary_op)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
{
if (unlikely(pc + sizeof(struct logical_op)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
- /* load */
+ /* load field ref */
case FILTER_OP_LOAD_FIELD_REF:
{
ERR("Unknown field ref type\n");
ret = -EINVAL;
break;
}
+ /* get context ref */
+ case FILTER_OP_GET_CONTEXT_REF:
+ {
+ ERR("Unknown field ref type\n");
+ ret = -EINVAL;
+ break;
+ }
case FILTER_OP_LOAD_FIELD_REF_STRING:
case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
case FILTER_OP_LOAD_FIELD_REF_S64:
case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
+ case FILTER_OP_GET_CONTEXT_REF_STRING:
+ case FILTER_OP_GET_CONTEXT_REF_S64:
+ case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
{
if (unlikely(pc + sizeof(struct load_op) + sizeof(struct field_ref)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
+ /* load from immediate operand */
case FILTER_OP_LOAD_STRING:
{
struct load_op *insn = (struct load_op *) pc;
if (unlikely(pc + sizeof(struct load_op)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
break;
}
str_len = strnlen(insn->data, maxlen);
if (unlikely(str_len >= maxlen)) {
/* Final '\0' not found within range */
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
{
if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_numeric)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
{
if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_double)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
{
if (unlikely(pc + sizeof(struct cast_op)
> start_pc + bytecode->len)) {
- ret = -EINVAL;
+ ret = -ERANGE;
}
break;
}
+
}
return ret;
ret = -EINVAL;
goto end;
}
- if ((vstack_ax(stack)->type != REG_DOUBLE && vstack_ax(stack)->type != REG_S64)
- || (vstack_bx(stack)-> type != REG_DOUBLE && vstack_bx(stack)->type != REG_S64)) {
- ERR("Unexpected register type for double comparator\n");
+ if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_DOUBLE) {
+ ERR("Double operator should have two double registers\n");
ret = -EINVAL;
goto end;
}
- if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_DOUBLE) {
- ERR("Double operator should have at least one double register\n");
+ break;
+ }
+
+ case FILTER_OP_EQ_DOUBLE_S64:
+ case FILTER_OP_NE_DOUBLE_S64:
+ case FILTER_OP_GT_DOUBLE_S64:
+ case FILTER_OP_LT_DOUBLE_S64:
+ case FILTER_OP_GE_DOUBLE_S64:
+ case FILTER_OP_LE_DOUBLE_S64:
+ {
+ if (!vstack_ax(stack) || !vstack_bx(stack)) {
+ ERR("Empty stack\n");
+ ret = -EINVAL;
+ goto end;
+ }
+ if (vstack_ax(stack)->type != REG_S64 && vstack_bx(stack)->type != REG_DOUBLE) {
+ ERR("Double-S64 operator has unexpected register types\n");
+ ret = -EINVAL;
+ goto end;
+ }
+ break;
+ }
+
+ case FILTER_OP_EQ_S64_DOUBLE:
+ case FILTER_OP_NE_S64_DOUBLE:
+ case FILTER_OP_GT_S64_DOUBLE:
+ case FILTER_OP_LT_S64_DOUBLE:
+ case FILTER_OP_GE_S64_DOUBLE:
+ case FILTER_OP_LE_S64_DOUBLE:
+ {
+ if (!vstack_ax(stack) || !vstack_bx(stack)) {
+ ERR("Empty stack\n");
+ ret = -EINVAL;
+ goto end;
+ }
+ if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_S64) {
+ ERR("S64-Double operator has unexpected register types\n");
ret = -EINVAL;
goto end;
}
break;
}
- /* load */
+ /* load field ref */
case FILTER_OP_LOAD_FIELD_REF:
{
ERR("Unknown field ref type\n");
break;
}
+ /* load from immediate operand */
case FILTER_OP_LOAD_STRING:
{
break;
break;
}
+ /* get context ref */
+ case FILTER_OP_GET_CONTEXT_REF:
+ {
+ ERR("Unknown get context ref type\n");
+ ret = -EINVAL;
+ goto end;
+ }
+ case FILTER_OP_GET_CONTEXT_REF_STRING:
+ {
+ struct load_op *insn = (struct load_op *) pc;
+ struct field_ref *ref = (struct field_ref *) insn->data;
+
+ dbg_printf("Validate get context ref offset %u type string\n",
+ ref->offset);
+ break;
+ }
+ case FILTER_OP_GET_CONTEXT_REF_S64:
+ {
+ struct load_op *insn = (struct load_op *) pc;
+ struct field_ref *ref = (struct field_ref *) insn->data;
+
+ dbg_printf("Validate get context ref offset %u type s64\n",
+ ref->offset);
+ break;
+ }
+ case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
+ {
+ struct load_op *insn = (struct load_op *) pc;
+ struct field_ref *ref = (struct field_ref *) insn->data;
+
+ dbg_printf("Validate get context ref offset %u type double\n",
+ ref->offset);
+ break;
+ }
+
}
end:
return ret;
case FILTER_OP_LT_DOUBLE:
case FILTER_OP_GE_DOUBLE:
case FILTER_OP_LE_DOUBLE:
+ case FILTER_OP_EQ_DOUBLE_S64:
+ case FILTER_OP_NE_DOUBLE_S64:
+ case FILTER_OP_GT_DOUBLE_S64:
+ case FILTER_OP_LT_DOUBLE_S64:
+ case FILTER_OP_GE_DOUBLE_S64:
+ case FILTER_OP_LE_DOUBLE_S64:
+ case FILTER_OP_EQ_S64_DOUBLE:
+ case FILTER_OP_NE_S64_DOUBLE:
+ case FILTER_OP_GT_S64_DOUBLE:
+ 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)) {
break;
}
- /* load */
+ /* load field ref */
case FILTER_OP_LOAD_FIELD_REF:
{
ERR("Unknown field ref type\n");
ret = -EINVAL;
goto end;
}
+ /* get context ref */
+ case FILTER_OP_GET_CONTEXT_REF:
+ {
+ ERR("Unknown get context ref type\n");
+ ret = -EINVAL;
+ goto end;
+ }
case FILTER_OP_LOAD_FIELD_REF_STRING:
case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
+ case FILTER_OP_GET_CONTEXT_REF_STRING:
{
if (vstack_push(stack)) {
ret = -EINVAL;
break;
}
case FILTER_OP_LOAD_FIELD_REF_S64:
+ case FILTER_OP_GET_CONTEXT_REF_S64:
{
if (vstack_push(stack)) {
ret = -EINVAL;
break;
}
case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
+ case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
{
if (vstack_push(stack)) {
ret = -EINVAL;
break;
}
+ /* load from immediate operand */
case FILTER_OP_LOAD_STRING:
{
struct load_op *insn = (struct load_op *) pc;
start_pc = &bytecode->data[0];
for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
pc = next_pc) {
- if (bytecode_validate_overflow(bytecode, start_pc, pc) != 0) {
- ERR("filter bytecode overflow\n");
- ret = -EINVAL;
+ ret = bytecode_validate_overflow(bytecode, start_pc, pc);
+ if (ret != 0) {
+ if (ret == -ERANGE)
+ ERR("filter bytecode overflow\n");
goto end;
}
dbg_printf("Validating op %s (%u)\n",