diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-21 08:56:43 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-21 08:56:43 -0800 |
commit | 7c0846125358f991d83f34ddde52956b196db3de (patch) | |
tree | e2054992b4f6962af7bfdf0cb7edec43f2611b32 /arch/m68k | |
parent | 609d3bc6230514a8ca79b377775b17e8c3d9ac93 (diff) |
m68k: remove broken strcmp implementation
The m68 hand-written assembler version of strcmp() has always been
broken: it returns the difference between the first non-matching byte
done as a 8-bit subtraction.
That is _almost_ right, but is broken for the overflow case. The
strcmp() function should indeed return the sign of the difference
between the first byte that differs, but the subtraction needs to be
done in a wider type than 'char'. Otherwise the ordering isn't actually
stable.
This went unnoticed for basically forever, because nobody ever cares
about non-US-ASCII orderings in the kernel (in fact, most users only
care about "exact match or not"), so overflows don't really happen in
practice, even if it was very very wrong.
But that mostly unnoticeable bug becomes very noticeable by the recent
change to make 'char' be unsigned in the kernel across all architectures
(commit 3bc753c06dd0: "kbuild: treat char as always unsigned"). Because
the code not only did the subtraction in the wrong type width, it also
used 'char' to then make the compiler expand the result from an 8-bit
difference to the 'int' return value.
So now with an unsigned char that incorrect arithmetic width was then
not even sign-expanded, and always returned just a positive integer.
We could re-instate the old broken code by just turning the 'char' into
'signed char' as has been done elsewhere where people depended on the
signedness of 'char', but since the whole function was broken to begin
with, and we have a non-broken default fallback implementation, let's
just remove this broken function entirely.
Reported-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/lkml/20221221145332.GA2399037@roeck-us.net/
Cc: Jason Donenfeld <Jason@zx2c4.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/include/asm/string.h | 20 |
1 files changed, 0 insertions, 20 deletions
diff --git a/arch/m68k/include/asm/string.h b/arch/m68k/include/asm/string.h index f759d944c449..f0f5021d6327 100644 --- a/arch/m68k/include/asm/string.h +++ b/arch/m68k/include/asm/string.h @@ -38,26 +38,6 @@ static inline char *strncpy(char *dest, const char *src, size_t n) return xdest; } -#ifndef CONFIG_COLDFIRE -#define __HAVE_ARCH_STRCMP -static inline int strcmp(const char *cs, const char *ct) -{ - char res; - - asm ("\n" - "1: move.b (%0)+,%2\n" /* get *cs */ - " cmp.b (%1)+,%2\n" /* compare a byte */ - " jne 2f\n" /* not equal, break out */ - " tst.b %2\n" /* at end of cs? */ - " jne 1b\n" /* no, keep going */ - " jra 3f\n" /* strings are equal */ - "2: sub.b -(%1),%2\n" /* *cs - *ct */ - "3:" - : "+a" (cs), "+a" (ct), "=d" (res)); - return res; -} -#endif /* CONFIG_COLDFIRE */ - #define __HAVE_ARCH_MEMMOVE extern void *memmove(void *, const void *, __kernel_size_t); |