Messages in this thread Patch in this message | | | Date | Thu, 06 Feb 2003 14:44:19 -0800 | From | Matthew Dobson <> | Subject | [patch] Broken CLEAR_BITMAP() macro |
| |
Hello all, It appears that the CLEAR_BITMAP() macro in include/linux/types.h is broken.
(Examples done with BITS_PER_LONG == 32, but would work with == 64, or anything but 8 for that matter! :)
>#define DECLARE_BITMAP(name,bits) \ > unsigned long name[((bits)+BITS_PER_LONG-1)/BITS_PER_LONG] >#define CLEAR_BITMAP(name,bits) \ > memset(name, 0, ((bits)+BITS_PER_LONG-1)/8)
If, for example, we DECLARE_BITMAP(foo, 64), we're going to get: unsigned long foo[((64)+32-1)/32] => unsigned long foo[95/32] => unsigned long foo[2]
Now, that's all well and good (and correct! ;) But, look at what happens if we do a CLEAR_BITMAP(foo, 64): memset(foo, 0, ((64)+32-1)/8) => memset(foo, 0, 95/8) => memset(foo, 0, 11)
So the memset is going to try and clear 11 bytes starting at foo, which will overflow the foo array by 3 bytes. This is bad.
What CLEAR_BITMAP wants to be doing is this: #define CLEAR_BITMAP(name,bits) \ memset(name, 0, (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long))
Attatched is a patch that creates a macro BITS_TO_LONGS that just rounds a number of bits up to the closest number of unsigned longs. This makes the DECLARE & CLEAR _BITMAP macros more readable. I also modify the CLEAR_BITMAP macro to work correctly.
Cheers!
-Matt diff -Nur --exclude-from=/usr/src/.dontdiff linux-2.5.59-vanilla/include/linux/types.h linux-2.5.59-bitmap_fix/include/linux/types.h --- linux-2.5.59-vanilla/include/linux/types.h Thu Jan 16 18:22:41 2003 +++ linux-2.5.59-bitmap_fix/include/linux/types.h Thu Feb 6 13:51:23 2003 @@ -4,10 +4,12 @@ #ifdef __KERNEL__ #include <linux/config.h> +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) #define DECLARE_BITMAP(name,bits) \ - unsigned long name[((bits)+BITS_PER_LONG-1)/BITS_PER_LONG] + unsigned long name[BITS_TO_LONGS(bits)] #define CLEAR_BITMAP(name,bits) \ - memset(name, 0, ((bits)+BITS_PER_LONG-1)/8) + memset(name, 0, BITS_TO_LONGS(bits)*sizeof(unsigned long)) #endif #include <linux/posix_types.h> | |