aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/string.h
diff options
context:
space:
mode:
authorMartin Wilck <mwilck@suse.com>2017-08-14 16:12:38 -0400
committerSagi Grimberg <sagi@grimberg.me>2017-08-28 16:00:41 -0400
commit01f33c336e2d298ea5d4ce5d6e5bcd12865cc30f (patch)
tree05ebf178ef681769d20767f63fe6f4a21f957a4a /include/linux/string.h
parent48fa362b6c3f4d69bdb6310b46626049092475e0 (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.h30
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)
200void fortify_panic(const char *name) __noreturn __cold; 200void fortify_panic(const char *name) __noreturn __cold;
201void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter"); 201void __read_overflow(void) __compiletime_error("detected read beyond size of object passed as 1st parameter");
202void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter"); 202void __read_overflow2(void) __compiletime_error("detected read beyond size of object passed as 2nd parameter");
203void __read_overflow3(void) __compiletime_error("detected read beyond size of object passed as 3rd parameter");
203void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter"); 204void __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_ */