Commit 32a9ff9cc55b42543a84bca90b070df92af72671
1 parent
fcec9bf124
Exists in
master
and in
39 other branches
lib/checksum.c: fix endianess bug
The new generic checksum code has a small dependency on endianess and worked only on big-endian systems. I could not find a nice efficient way to express this, so I added an #ifdef. Using 'result += le16_to_cpu(*buff);' would have worked as well, but would be slightly less efficient on big-endian systems and IMHO would not be clearer. Also fix a bug that prevents this from working on 64-bit machines. If you have a 64-bit CPU and want to use the generic checksum code, you should probably do some more optimizations anyway, but at least the code should not break. Reported-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Showing 1 changed file with 9 additions and 1 deletions Side-by-side Diff
lib/checksum.c
... | ... | @@ -55,7 +55,11 @@ |
55 | 55 | goto out; |
56 | 56 | odd = 1 & (unsigned long) buff; |
57 | 57 | if (odd) { |
58 | +#ifdef __LITTLE_ENDIAN | |
58 | 59 | result = *buff; |
60 | +#else | |
61 | + result += (*buff << 8); | |
62 | +#endif | |
59 | 63 | len--; |
60 | 64 | buff++; |
61 | 65 | } |
... | ... | @@ -71,7 +75,7 @@ |
71 | 75 | if (count) { |
72 | 76 | unsigned long carry = 0; |
73 | 77 | do { |
74 | - unsigned long w = *(unsigned long *) buff; | |
78 | + unsigned long w = *(unsigned int *) buff; | |
75 | 79 | count--; |
76 | 80 | buff += 4; |
77 | 81 | result += carry; |
78 | 82 | |
... | ... | @@ -87,7 +91,11 @@ |
87 | 91 | } |
88 | 92 | } |
89 | 93 | if (len & 1) |
94 | +#ifdef __LITTLE_ENDIAN | |
95 | + result += *buff; | |
96 | +#else | |
90 | 97 | result += (*buff << 8); |
98 | +#endif | |
91 | 99 | result = from32to16(result); |
92 | 100 | if (odd) |
93 | 101 | result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); |