diff options
author | Martin Wilck <mwilck@suse.com> | 2017-08-14 16:12:38 -0400 |
---|---|---|
committer | Sagi Grimberg <sagi@grimberg.me> | 2017-08-28 16:00:41 -0400 |
commit | 01f33c336e2d298ea5d4ce5d6e5bcd12865cc30f (patch) | |
tree | 05ebf178ef681769d20767f63fe6f4a21f957a4a /include/linux/string.h | |
parent | 48fa362b6c3f4d69bdb6310b46626049092475e0 (diff) |
string.h: add memcpy_and_pad()
This helper function is useful for the nvme subsystem, and maybe
others.
Note: the warnings reported by the kbuild test robot for this patch
are actually generated by the use of CONFIG_PROFILE_ALL_BRANCHES
together with __FORTIFY_INLINE.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Sagi Grimberg <sagi@grimbeg.me>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'include/linux/string.h')
-rw-r--r-- | include/linux/string.h | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/include/linux/string.h b/include/linux/string.h index a467e617eeb0..0bec4151b0eb 100644 --- a/include/linux/string.h +++ b/include/linux/string.h | |||
@@ -200,6 +200,7 @@ static inline const char *kbasename(const char *path) | |||
200 | void fortify_panic(const char *name) __noreturn __cold; | 200 | void fortify_panic(const char *name) __noreturn __cold; |
201 | void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter"); | 201 | void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter"); |
202 | void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter"); | 202 | void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter"); |
203 | void __read_overflow3(void) __compiletime_error("detected read beyond size of object passed as 3rd parameter"); | ||
203 | void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter"); | 204 | void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter"); |
204 | 205 | ||
205 | #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE) | 206 | #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE) |
@@ -395,4 +396,33 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q) | |||
395 | 396 | ||
396 | #endif | 397 | #endif |
397 | 398 | ||
399 | /** | ||
400 | * memcpy_and_pad - Copy one buffer to another with padding | ||
401 | * @dest: Where to copy to | ||
402 | * @dest_len: The destination buffer size | ||
403 | * @src: Where to copy from | ||
404 | * @count: The number of bytes to copy | ||
405 | * @pad: Character to use for padding if space is left in destination. | ||
406 | */ | ||
407 | __FORTIFY_INLINE void memcpy_and_pad(void *dest, size_t dest_len, | ||
408 | const void *src, size_t count, int pad) | ||
409 | { | ||
410 | size_t dest_size = __builtin_object_size(dest, 0); | ||
411 | size_t src_size = __builtin_object_size(src, 0); | ||
412 | |||
413 | if (__builtin_constant_p(dest_len) && __builtin_constant_p(count)) { | ||
414 | if (dest_size < dest_len && dest_size < count) | ||
415 | __write_overflow(); | ||
416 | else if (src_size < dest_len && src_size < count) | ||
417 | __read_overflow3(); | ||
418 | } | ||
419 | if (dest_size < dest_len) | ||
420 | fortify_panic(__func__); | ||
421 | if (dest_len > count) { | ||
422 | memcpy(dest, src, count); | ||
423 | memset(dest + count, pad, dest_len - count); | ||
424 | } else | ||
425 | memcpy(dest, src, dest_len); | ||
426 | } | ||
427 | |||
398 | #endif /* _LINUX_STRING_H_ */ | 428 | #endif /* _LINUX_STRING_H_ */ |