From 56d01184e3b69688dec04bd97a3017df9462f4fc Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Sat, 4 Jul 2020 13:54:43 +0200 Subject: executor: fix bitfields for big-endian arch Add bitfield tests for big-endian arch Issue: #1885 Signed-off-by: Alexander Egorenkov --- executor/executor.cc | 12 +++++++++++- executor/test.h | 13 +++++++++++-- pkg/csource/csource.go | 8 ++++++-- sys/test/test/bf2_be | 25 +++++++++++++++++++++++++ sys/test/test/bf_be | 6 ++++++ 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 sys/test/test/bf2_be create mode 100644 sys/test/test/bf_be diff --git a/executor/executor.cc b/executor/executor.cc index d0b352fc8..1e7625d7e 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -1157,12 +1158,21 @@ void copyin_int(char* addr, uint64 val, uint64 bf, uint64 bf_off, uint64 bf_len) return; } T x = swap(*(T*)addr, sizeof(T), bf); - x = (x & ~BITMASK(bf_off, bf_len)) | ((val << bf_off) & BITMASK(bf_off, bf_len)); + debug_verbose("copyin_int<%zu>: old x=0x%llx\n", sizeof(T), (uint64)x); +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + const uint64 shift = sizeof(T) * CHAR_BIT - bf_off - bf_len; +#else + const uint64 shift = bf_off; +#endif + x = (x & ~BITMASK(shift, bf_len)) | ((val << shift) & BITMASK(shift, bf_len)); + debug_verbose("copyin_int<%zu>: new x=0x%llx\n", sizeof(T), (uint64)x); *(T*)addr = swap(x, sizeof(T), bf); } void copyin(char* addr, uint64 val, uint64 size, uint64 bf, uint64 bf_off, uint64 bf_len) { + debug_verbose("copyin: addr=%p val=0x%llx size=%llu bf=%llu bf_off=%llu bf_len=%llu\n", + addr, val, size, bf, bf_off, bf_len); if (bf != binary_format_native && bf != binary_format_bigendian && (bf_off != 0 || bf_len != 0)) fail("bitmask for string format %llu/%llu", bf_off, bf_len); switch (bf) { diff --git a/executor/test.h b/executor/test.h index 0d3587b84..cec0228e2 100644 --- a/executor/test.h +++ b/executor/test.h @@ -14,7 +14,7 @@ static int test_copyin() if (x[0] != 0 || x[1] != 0 || x[2] != 0x34 || x[3] != 0x12 || x[4] != 0 || x[5] != 0) { - printf("bad result of STORE_BY_BITMASK(0, 0): %x %x %x %x %x %x\n", + printf("bad result of STORE_BY_BITMASK(le16, 0x1234, 0, 16): %x %x %x %x %x %x\n", x[0], x[1], x[2], x[3], x[4], x[5]); return 1; } @@ -23,7 +23,16 @@ static int test_copyin() if (x[0] != 0 || x[1] != 0 || x[2] != 0x54 || x[3] != 0x13 || x[4] != 0 || x[5] != 0) { - printf("bad result of STORE_BY_BITMASK(7, 3): %x %x %x %x %x %x\n", + printf("bad result of STORE_BY_BITMASK(le16, 0x555a, 5, 4): %x %x %x %x %x %x\n", + x[0], x[1], x[2], x[3], x[4], x[5]); + return 1; + } + STORE_BY_BITMASK(uint16, htobe16, &buf[1], 0x4567, 13, 3); + memcpy(x, buf, sizeof(x)); + if (x[0] != 0 || x[1] != 0 || + x[2] != 0xf4 || x[3] != 0x13 || + x[4] != 0 || x[5] != 0) { + printf("bad result of STORE_BY_BITMASK(be16, 0x4567, 13, 3): %x %x %x %x %x %x\n", x[0], x[1], x[2], x[3], x[4], x[5]); return 1; } diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go index 4126e2b02..2eda7c76d 100644 --- a/pkg/csource/csource.go +++ b/pkg/csource/csource.go @@ -313,12 +313,16 @@ func (ctx *context) copyin(w *bytes.Buffer, csumSeq *int, copyin prog.ExecCopyin panic("bitfield+string format") } htobe := "" - if arg.Format == prog.FormatBigEndian { + if ctx.target.LittleEndian && arg.Format == prog.FormatBigEndian { htobe = fmt.Sprintf("htobe%v", arg.Size*8) } + bitfieldOffset := arg.BitfieldOffset + if !ctx.target.LittleEndian { + bitfieldOffset = arg.Size*8 - arg.BitfieldOffset - arg.BitfieldLength + } fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v, %v, 0x%x, %v, %v, %v));\n", arg.Size*8, htobe, copyin.Addr, ctx.constArgToStr(arg, false, false), - arg.BitfieldOffset, arg.BitfieldLength) + bitfieldOffset, arg.BitfieldLength) } case prog.ExecArgResult: ctx.copyinVal(w, copyin.Addr, arg.Size, ctx.resultArgToStr(arg), arg.Format) diff --git a/sys/test/test/bf2_be b/sys/test/test/bf2_be new file mode 100644 index 000000000..094c3f6e2 --- /dev/null +++ b/sys/test/test/bf2_be @@ -0,0 +1,25 @@ +# 32_shmem has 4-byte alignment for int64 and everything goes havoc. +# requires: -arch=32_shmem -littleendian + +syz_compare(&AUTO="1200000034607800", AUTO, &AUTO=@bf4={0x12, {0x34, 0x56, 0x78}}, AUTO) +syz_compare(&AUTO="1200000034600000", AUTO, &AUTO=@bf5={0x12, {0x34, 0x56}}, AUTO) +syz_compare(&AUTO="120034607800", AUTO, &AUTO=@bf6={0x12, {0x34, 0x56, 0x78}}, AUTO) +syz_compare(&AUTO="12003460", AUTO, &AUTO=@bf7={0x12, {0x34, 0x56}}, AUTO) +syz_compare(&AUTO="1200000034680000", AUTO, &AUTO=@bf8={0x12, {0x34, 0x56, 0x78}}, AUTO) +syz_compare(&AUTO="12003468", AUTO, &AUTO=@bf9={0x12, {0x34, 0x56, 0x78}}, AUTO) +syz_compare(&AUTO="120000000000000034567890abcdef102340ab0000000000", AUTO, &AUTO=@bf10={0x12, {0x3, 0x4, 0x5, 0x678, 0x90a, 0xbcd, 0xef1, 0x234, 0xab}}, AUTO) +syz_compare(&AUTO="120000003456789a", AUTO, &AUTO=@bf11={0x12, {0x34, 0x56, 0x78, 0x9, 0xa}}, AUTO) +syz_compare(&AUTO="120000003456789ab0cd0000", AUTO, &AUTO=@bf12={0x12, {0x34, 0x56, 0x78, 0x9, 0xa, 0xb, 0xcd}}, AUTO) +syz_compare(&AUTO="1200000034567890abc00000", AUTO, &AUTO=@bf13={0x12, {0x3456, 0x789, 0xabc}}, AUTO) +syz_compare(&AUTO="1200000034567890", AUTO, &AUTO=@bf14={0x12, {0x34, 0x56, 0x789}}, AUTO) +syz_compare(&AUTO="1200000034567800", AUTO, &AUTO=@bf15={0x12, {0x34, 0x567, 0x8}}, AUTO) +syz_compare(&AUTO="1200000034560000", AUTO, &AUTO=@bf16={0x12, {0x34, 0x5, 0x6}}, AUTO) +syz_compare(&AUTO="1200000034146000", AUTO, &AUTO=@bf17={0x12, {0x34, 0x5, 0x6}}, AUTO) +syz_compare(&AUTO="1200000034501800", AUTO, &AUTO=@bf18={0x12, {0x34, 0x5, 0x6}}, AUTO) +syz_compare(&AUTO="120034005670", AUTO, &AUTO=@bf19={0x12, {0x34, 0x567}}, AUTO) +syz_compare(&AUTO="12000000000000003456789a00000000", AUTO, &AUTO=@bf20={0x12, {0x34, 0x56, 0x7, 0x8, 0x9, 0xa}}, AUTO) +syz_compare(&AUTO="1200000033333333456789ab", AUTO, &AUTO=@bf21={0x12, {0x33333333, 0x45, 0x67, 0x89ab}}, AUTO) +syz_compare(&AUTO="123456", AUTO, &AUTO=@bf22={0x12, {0x34, 0x5, 0x6}}, AUTO) +syz_compare(&AUTO="12345d80", AUTO, &AUTO=@bf23={0x12, {0x34, 0x5, 0x36}}, AUTO) +syz_compare(&AUTO="123450", AUTO, &AUTO=@bf24={0x12, {0x34, 0x5}}, AUTO) +syz_compare(&AUTO="1200000000aa02efbbcc0000", AUTO, &AUTO=@bf25={0x12, {0xaa, 0xbb, 0x1, 0x1, 0xbbcc, ''}}, AUTO) diff --git a/sys/test/test/bf_be b/sys/test/test/bf_be new file mode 100644 index 000000000..4c7fc85ec --- /dev/null +++ b/sys/test/test/bf_be @@ -0,0 +1,6 @@ +# 32_shmem has 4-byte alignment for int64 and everything goes havoc. +# requires: -arch=32_shmem -littleendian + +syz_compare(&AUTO="eac0000000000000cdcdcdcdcdcdcdcd5fffffc075607560aa", 0x20, &AUTO=@bf0={0xabab, 0xcdcdcdcdcdcdcdcd, 0xabab, 0xffff, 0xffffff, 0xabab, 0xabab, 0xaaa}, AUTO) +syz_compare(&AUTO="ccddef23456ef120", 0x8, &AUTO=@bf2={0x0abc, 0x0bcd, 0xcdef, 0x123456, 0x78ef12}, AUTO) +syz_compare(&AUTO="ccddef23456ef120", 0x8, &AUTO=@bf3={0x0abc, 0x0bcd, 0xcdef, 0x123456, 0x78ef12}, AUTO) -- cgit mrf-deployment