There were multiple bugs with immediate values in shift instructions. The code was not masking as required by RFC.
Add new tests that cover these instructions. Signed-off-by: Stephen Hemminger <[email protected]> --- app/test/test_bpf.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c index 232e9e2a98..0e5894a532 100644 --- a/app/test/test_bpf.c +++ b/app/test/test_bpf.c @@ -2005,6 +2005,51 @@ test_div1_check(uint64_t rc, const void *arg) return cmp_res(__func__, 0, rc, dve.out, dvt->out, sizeof(dve.out)); } +/* + * Shift counts are masked to the operand width (RFC 9669: 0x3f for 64-bit, + * 0x1f for 32-bit). Counts >= 128 also exercise the x86 imm_size() path that + * used to desync the stream, and the arm64 UBFM/SBFM immediate encoding. + */ +static const struct ebpf_insn test_shift_big_imm_prog[] = { + { + .code = (EBPF_ALU64 | EBPF_MOV | BPF_K), + .dst_reg = EBPF_REG_0, + .imm = 1 + }, + { + .code = (EBPF_ALU64 | BPF_LSH | BPF_K), + .dst_reg = EBPF_REG_0, + .imm = 191 + }, + { + .code = (EBPF_ALU64 | EBPF_ARSH | BPF_K), + .dst_reg = EBPF_REG_0, + .imm = 200 + }, + { + .code = (EBPF_ALU64 | BPF_RSH | BPF_K), + .dst_reg = EBPF_REG_0, + .imm = 130 + }, + { + .code = (BPF_JMP | EBPF_EXIT) + }, +}; + +static void +test_shift_big_imm_prepare(void *arg) +{ + memset(arg, 0, sizeof(struct dummy_offset)); +} + +static int +test_shift_big_imm_check(uint64_t rc, const void *arg) +{ + uint64_t expect = 0x3FE0000000000000ULL; + + return cmp_res(__func__, expect, rc, arg, arg, 0); +} + /* call test-cases */ static const struct ebpf_insn test_call1_prog[] = { @@ -3409,6 +3454,20 @@ static const struct bpf_test tests[] = { .prepare = test_mul1_prepare, .check_result = test_div1_check, }, + { + .name = "test_shift_big_imm", + .arg_sz = sizeof(struct dummy_offset), + .prm = { + .ins = test_shift_big_imm_prog, + .nb_ins = RTE_DIM(test_shift_big_imm_prog), + .prog_arg = { + .type = RTE_BPF_ARG_PTR, + .size = sizeof(struct dummy_offset), + }, + }, + .prepare = test_shift_big_imm_prepare, + .check_result = test_shift_big_imm_check, + }, { .name = "test_call1", .arg_sz = sizeof(struct dummy_offset), -- 2.53.0

