iio: iio-utils: Fix possible incorrect mask calculation [Linux 4.4.187]

This Linux kernel change "iio: iio-utils: Fix possible incorrect mask calculation" is included in the Linux 4.4.187 release. This change is authored by Bastien Nocera <hadess [at] hadess.net> on Thu Jun 27 09:20:45 2019 +0200. The commit for this change in Linux stable tree is 623c3a6 (patch) which is from upstream commit 208a68c. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 208a68c.

iio: iio-utils: Fix possible incorrect mask calculation

[ Upstream commit 208a68c8393d6041a90862992222f3d7943d44d6 ]

On some machines, iio-sensor-proxy was returning all 0's for IIO sensor
values. It turns out that the bits_used for this sensor is 32, which makes
the mask calculation:

*mask = (1 << 32) - 1;

If the compiler interprets the 1 literals as 32-bit ints, it generates
undefined behavior depending on compiler version and optimization level.
On my system, it optimizes out the shift, so the mask value becomes

*mask = (1) - 1;

With a mask value of 0, iio-sensor-proxy will always return 0 for every axis.

Avoid incorrect 0 values caused by compiler optimization.

See original fix by Brett Dutro <brett.dutro@gmail.com> in
iio-sensor-proxy:
https://github.com/hadess/iio-sensor-proxy/commit/9615ceac7c134d838660e209726cd86aa2064fd3

Signed-off-by: Bastien Nocera <hadess@hadess.net>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>

There are 4 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 tools/iio/iio_utils.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
index 5eb6793..2d0dcd6 100644
--- a/tools/iio/iio_utils.c
+++ b/tools/iio/iio_utils.c
@@ -163,9 +163,9 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
            *be = (endianchar == 'b');
            *bytes = padint / 8;
            if (*bits_used == 64)
-               *mask = ~0;
+               *mask = ~(0ULL);
            else
-               *mask = (1ULL << *bits_used) - 1;
+               *mask = (1ULL << *bits_used) - 1ULL;

            *is_signed = (signchar == 's');
            if (fclose(sysfsfp)) {

Leave a Reply

Your email address will not be published. Required fields are marked *