aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Egorenkov <Alexander.Egorenkov@ibm.com>2020-07-04 13:54:43 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-07-10 10:25:58 +0200
commit56d01184e3b69688dec04bd97a3017df9462f4fc (patch)
tree791934110ceb23e2e45aae0b76242c240003b3f4
parentedf162e8c360dd578d20a86c4ad79b54747a2d64 (diff)
executor: fix bitfields for big-endian arch
Add bitfield tests for big-endian arch Issue: #1885 Signed-off-by: Alexander Egorenkov <Alexander.Egorenkov@ibm.com>
-rw-r--r--executor/executor.cc12
-rw-r--r--executor/test.h13
-rw-r--r--pkg/csource/csource.go8
-rw-r--r--sys/test/test/bf2_be25
-rw-r--r--sys/test/test/bf_be6
5 files changed, 59 insertions, 5 deletions
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 <algorithm>
#include <errno.h>
+#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
@@ -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)