Fix: overflow of signed integer results in undefined behaviour
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 3 May 2016 02:46:28 +0000 (22:46 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 3 May 2016 02:46:28 +0000 (22:46 -0400)
The expression "min_value = -((int64_t)1 << (size - 1))"

will result in a signed integer overflow when size is 64
((1ULL << 63) > LONG_MAX).

Note that larger sizes are unsupported and checked for in the setter.

Signed overflows result in undefined behaviour and llvm takes
advantage of this to optimize away the range check

"if (value < min_value || value > max_value) {"

Surprisingly, this was not catched by GCC, Coverity, scan-build or
cppcheck.

The fix consists in computing both bounds using an unsigned long long
type and, in the case of the lower bound, negating it (resulting in a
long long).

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
formats/ctf/ir/fields.c

index 3ca57bb017ba097bce5517fd17735a1cbf08c168..58f69fd43cbd5e674412e05c7a4f11afe706834f 100644 (file)
@@ -928,8 +928,8 @@ int bt_ctf_field_signed_integer_set_value(struct bt_ctf_field *field,
        }
 
        size = integer_type->declaration.len;
-       min_value = -((int64_t)1 << (size - 1));
-       max_value = ((int64_t)1 << (size - 1)) - 1;
+       min_value = -(1ULL << (size - 1));
+       max_value = (1ULL << (size - 1)) - 1;
        if (value < min_value || value > max_value) {
                ret = -1;
                goto end;
This page took 0.025936 seconds and 4 git commands to generate.