From 88b3880c7741be50c1aacf7c85b1e719ba5da2a4 Mon Sep 17 00:00:00 2001 From: Johannes Schlatow Date: Mon, 16 Aug 2021 18:17:20 +0200 Subject: [PATCH] base: fix shift overflow error in Bitfield::mask() Fixes genodelabs/genode#4249 --- repos/base/include/util/register.h | 10 ++++++- repos/base/src/test/mmio/main.cc | 42 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/repos/base/include/util/register.h b/repos/base/include/util/register.h index d2b6bf4134..4cc25d6cc7 100644 --- a/repos/base/include/util/register.h +++ b/repos/base/include/util/register.h @@ -149,7 +149,15 @@ struct Genode::Register /** * Get an unshifted mask of this field */ - static constexpr access_t mask() { return ((access_t)1 << WIDTH) - 1; } + static constexpr access_t mask() + { + /* prevent compile error "left shift count >= width of type" */ + if (_WIDTH < _ACCESS_WIDTH) { + return ((access_t)1 << _WIDTH) - 1; + } else { + return ~(access_t)0; + } + } /** * Get a mask of this field shifted by its shift in the register diff --git a/repos/base/src/test/mmio/main.cc b/repos/base/src/test/mmio/main.cc index 418a83b16e..1738ae3322 100644 --- a/repos/base/src/test/mmio/main.cc +++ b/repos/base/src/test/mmio/main.cc @@ -69,6 +69,10 @@ struct Test_mmio : public Mmio struct Bits_2 : Bitfield<44,4> { }; struct Bits_3 : Bitfield<0,24> { }; struct Bits_4 : Bitfield<60,4> { }; + struct Bits_5 : Bitfield<0,64> { }; + struct Bits_6 : Bitfield<16,64> { }; + struct Bits_7 : Bitfield<12,90> { }; + struct Bits_8 : Bitfield<0,72> { }; }; struct Bitset_64_0 : Bitset_2 { }; struct Bitset_64_1 : Bitset_3 { }; @@ -463,6 +467,44 @@ void Component::construct(Genode::Env &env) if (mmio.read() != BITS_3) { failed(__LINE__, env); } if (compare_mem(mmio_mem, cmp_mem, MMIO_SIZE)) { failed(__LINE__, env); } + /* test bitfields that are at least as wide as the register */ + { + uint64_t const value_1 { 0x0123456789abcdef }; + uint64_t const value_2 { 0x0123456789abcdef }; + uint64_t const value_3 { 0x0123456789abcdef }; + zero_mem(mmio_mem, MMIO_SIZE); + mmio.write(value_1); + if (mmio.read() != value_2) { failed(__LINE__, env); } + if (compare_mem(mmio_mem, (uint8_t *)&value_3, MMIO_SIZE)) { failed(__LINE__, env); } + } + { + uint64_t const value_1 { 0x0123456789abcdef }; + uint64_t const value_2 { 0x0000456789abcdef }; + uint64_t const value_3 { 0x456789abcdef0000 }; + zero_mem(mmio_mem, MMIO_SIZE); + mmio.write(value_1); + if (mmio.read() != value_2) { failed(__LINE__, env); } + if (compare_mem(mmio_mem, (uint8_t *)&value_3, MMIO_SIZE)) { failed(__LINE__, env); } + } + { + uint64_t const value_1 { 0x0123456789abcdef }; + uint64_t const value_2 { 0x0003456789abcdef }; + uint64_t const value_3 { 0x3456789abcdef000 }; + zero_mem(mmio_mem, MMIO_SIZE); + mmio.write(value_1); + if (mmio.read() != value_2) { failed(__LINE__, env); } + if (compare_mem(mmio_mem, (uint8_t *)&value_3, MMIO_SIZE)) { failed(__LINE__, env); } + } + { + uint64_t const value_1 { 0x0123456789abcdef }; + uint64_t const value_2 { 0x0123456789abcdef }; + uint64_t const value_3 { 0x0123456789abcdef }; + zero_mem(mmio_mem, MMIO_SIZE); + mmio.write(value_1); + if (mmio.read() != value_2) { failed(__LINE__, env); } + if (compare_mem(mmio_mem, (uint8_t *)&value_3, MMIO_SIZE)) { failed(__LINE__, env); } + } + /* bitsets */ typedef Test_mmio::Bitset_64 Bitset; enum { BITSET = 0x4abcdef056789123 };