aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common.h
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-01-17 19:04:37 +0100
committerDmitry Vyukov <dvyukov@google.com>2017-01-17 19:04:37 +0100
commit1ac75f06add54089e4910ecb6a97198336155c63 (patch)
treee7d5219d6589e4ef018a5b5822a4da05b9249300 /executor/common.h
parent8ead82246bc00830d0271933df316e973be4ebcc (diff)
executor: fix copyin of values
Currently non-bitfield values are copied incorrectly. Probably all turned into zeros or something. Fix that. Add test.
Diffstat (limited to 'executor/common.h')
-rw-r--r--executor/common.h24
1 files changed, 13 insertions, 11 deletions
diff --git a/executor/common.h b/executor/common.h
index 40b2bf8d0..5c5bb1032 100644
--- a/executor/common.h
+++ b/executor/common.h
@@ -158,17 +158,19 @@ static void install_segv_handler()
__atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \
}
-#define BITMASK_LEN(type, bf_len) (type)((1ul << bf_len) - 1)
-
-#define BITMASK_LEN_OFF(type, bf_off, bf_len) (type)(BITMASK_LEN(type, bf_len) << bf_off)
-
-#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \
- do { \
- type new_val = *(type*)addr; \
- new_val &= ~BITMASK_LEN_OFF(type, bf_off, bf_len); \
- new_val |= ((type)val & BITMASK_LEN(type, bf_len)) << bf_off; \
- *(type*)addr = new_val; \
- } while (0)
+#define BITMASK_LEN(type, bf_len) (type)((1ull << (bf_len)) - 1)
+
+#define BITMASK_LEN_OFF(type, bf_off, bf_len) (type)(BITMASK_LEN(type, (bf_len)) << (bf_off))
+
+#define STORE_BY_BITMASK(type, addr, val, bf_off, bf_len) \
+ if ((bf_off) == 0 && (bf_len) == 0) { \
+ *(type*)(addr) = (val); \
+ } else { \
+ type new_val = *(type*)(addr); \
+ new_val &= ~BITMASK_LEN_OFF(type, (bf_off), (bf_len)); \
+ new_val |= ((type)(val)&BITMASK_LEN(type, (bf_len))) << (bf_off); \
+ *(type*)(addr) = new_val; \
+ }
#ifdef __NR_syz_emit_ethernet
static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)