Skip to content

Commit 5c4e0a2

Browse files
groecktorvalds
authored andcommitted
string: uninline memcpy_and_pad
When building m68k:allmodconfig, recent versions of gcc generate the following error if the length of UTS_RELEASE is less than 8 bytes. In function 'memcpy_and_pad', inlined from 'nvmet_execute_disc_identify' at drivers/nvme/target/discovery.c:268:2: arch/m68k/include/asm/string.h:72:25: error: '__builtin_memcpy' reading 8 bytes from a region of size 7 Discussions around the problem suggest that this only happens if an architecture does not provide strlen(), if -ffreestanding is provided as compiler option, and if CONFIG_FORTIFY_SOURCE=n. All of this is the case for m68k. The exact reasons are unknown, but seem to be related to the ability of the compiler to evaluate the return value of strlen() and the resulting execution flow in memcpy_and_pad(). It would be possible to work around the problem by using sizeof(UTS_RELEASE) instead of strlen(UTS_RELEASE), but that would only postpone the problem until the function is called in a similar way. Uninline memcpy_and_pad() instead to solve the problem for good. Suggested-by: Linus Torvalds <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Acked-by: Andy Shevchenko <[email protected]> Signed-off-by: Guenter Roeck <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 655feda commit 5c4e0a2

File tree

2 files changed

+22
-17
lines changed

2 files changed

+22
-17
lines changed

include/linux/string.h

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -253,23 +253,8 @@ static inline const char *kbasename(const char *path)
253253
#include <linux/fortify-string.h>
254254
#endif
255255

256-
/**
257-
* memcpy_and_pad - Copy one buffer to another with padding
258-
* @dest: Where to copy to
259-
* @dest_len: The destination buffer size
260-
* @src: Where to copy from
261-
* @count: The number of bytes to copy
262-
* @pad: Character to use for padding if space is left in destination.
263-
*/
264-
static inline void memcpy_and_pad(void *dest, size_t dest_len,
265-
const void *src, size_t count, int pad)
266-
{
267-
if (dest_len > count) {
268-
memcpy(dest, src, count);
269-
memset(dest + count, pad, dest_len - count);
270-
} else
271-
memcpy(dest, src, dest_len);
272-
}
256+
void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
257+
int pad);
273258

274259
/**
275260
* memset_after - Set a value after a struct member to the end of a struct

lib/string_helpers.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,26 @@ char *strreplace(char *s, char old, char new)
883883
}
884884
EXPORT_SYMBOL(strreplace);
885885

886+
/**
887+
* memcpy_and_pad - Copy one buffer to another with padding
888+
* @dest: Where to copy to
889+
* @dest_len: The destination buffer size
890+
* @src: Where to copy from
891+
* @count: The number of bytes to copy
892+
* @pad: Character to use for padding if space is left in destination.
893+
*/
894+
void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
895+
int pad)
896+
{
897+
if (dest_len > count) {
898+
memcpy(dest, src, count);
899+
memset(dest + count, pad, dest_len - count);
900+
} else {
901+
memcpy(dest, src, dest_len);
902+
}
903+
}
904+
EXPORT_SYMBOL(memcpy_and_pad);
905+
886906
#ifdef CONFIG_FORTIFY_SOURCE
887907
void fortify_panic(const char *name)
888908
{

0 commit comments

Comments
 (0)