diff options
| author | Maxime Ripard <mripard@kernel.org> | 2024-12-02 12:44:18 +0100 |
|---|---|---|
| committer | Maxime Ripard <mripard@kernel.org> | 2024-12-02 12:44:18 +0100 |
| commit | 3aba2eba84e0219fb66061359052be81bd883d53 (patch) | |
| tree | 36da31539acaa6c360d0b606103d90926ac04e50 /lib/string.c | |
| parent | 44cff6c5b0b17a78bc0b30372bcd816cf6dd282a (diff) | |
| parent | 40384c840ea1944d7c5a392e8975ed088ecf0b37 (diff) | |
Merge drm/drm-next into drm-misc-next
Kickstart 6.14 cycle.
Signed-off-by: Maxime Ripard <mripard@kernel.org>
Diffstat (limited to 'lib/string.c')
| -rw-r--r-- | lib/string.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/lib/string.c b/lib/string.c index 76327b51e36f..eb4486ed40d2 100644 --- a/lib/string.c +++ b/lib/string.c @@ -104,6 +104,12 @@ char *strncpy(char *dest, const char *src, size_t count) EXPORT_SYMBOL(strncpy); #endif +#ifdef __BIG_ENDIAN +# define ALLBUTLAST_BYTE_MASK (~255ul) +#else +# define ALLBUTLAST_BYTE_MASK (~0ul >> 8) +#endif + ssize_t sized_strscpy(char *dest, const char *src, size_t count) { const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; @@ -147,13 +153,18 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count) *(unsigned long *)(dest+res) = c & zero_bytemask(data); return res + find_zero(data); } + count -= sizeof(unsigned long); + if (unlikely(!count)) { + c &= ALLBUTLAST_BYTE_MASK; + *(unsigned long *)(dest+res) = c; + return -E2BIG; + } *(unsigned long *)(dest+res) = c; res += sizeof(unsigned long); - count -= sizeof(unsigned long); max -= sizeof(unsigned long); } - while (count) { + while (count > 1) { char c; c = src[res]; @@ -164,11 +175,11 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count) count--; } - /* Hit buffer length without finding a NUL; force NUL-termination. */ - if (res) - dest[res-1] = '\0'; + /* Force NUL-termination. */ + dest[res] = '\0'; - return -E2BIG; + /* Return E2BIG if the source didn't stop */ + return src[res] ? -E2BIG : res; } EXPORT_SYMBOL(sized_strscpy); |
