]> granicus.if.org Git - strace/commitdiff
evdev: fix array size calculation in decode_bitset_
authorEugene Syromyatnikov <evgsyr@gmail.com>
Fri, 12 Jul 2019 12:57:28 +0000 (14:57 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Sat, 13 Jul 2019 11:48:01 +0000 (11:48 +0000)
max_nr is in bits (as it is a number of flags), result is in bytes, and
the array allocation has to be in personality words.

There's still an open question, however, what to do on big-endian
architectures when a non-divisible-by-4 value is returned.

* evdev.c (decode_bitset_): Declare size_bits, initialise it and use it
later instead of size; round up size by personality's word boundary.

evdev.c

diff --git a/evdev.c b/evdev.c
index 4b811cf8f157e95c32f98847f463ed7dc182f845..a3d9cb5536e6985fa3f4ab704e599bf4deadf642 100644 (file)
--- a/evdev.c
+++ b/evdev.c
@@ -151,10 +151,14 @@ decode_bitset_(struct tcb *const tcp, const kernel_ulong_t arg,
        tprints(", ");
 
        unsigned int size;
+       unsigned int size_bits;
+
        if ((kernel_ulong_t) tcp->u_rval > max_nr / 8)
-               size = max_nr;
+               size_bits = max_nr;
        else
-               size = tcp->u_rval * 8;
+               size_bits = tcp->u_rval * 8;
+
+       size = ROUNDUP(ROUNDUP_DIV(size_bits, 8), current_wordsize);
 
        if (syserror(tcp) || !size) {
                printaddr(arg);
@@ -170,13 +174,13 @@ decode_bitset_(struct tcb *const tcp, const kernel_ulong_t arg,
        tprints("[");
 
        int bit_displayed = 0;
-       int i = next_set_bit(decoded_arg, 0, size);
+       int i = next_set_bit(decoded_arg, 0, size_bits);
        if (i < 0) {
                tprints(" 0 ");
        } else {
                printxval_dispatch(decode_nr, decode_nr_size, i, dflt, xt);
 
-               while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) {
+               while ((i = next_set_bit(decoded_arg, i + 1, size_bits)) > 0) {
                        if (abbrev(tcp) && bit_displayed >= 3) {
                                tprints(", ...");
                                break;