summaryrefslogtreecommitdiff
path: root/lib/string.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2024-12-05 11:48:58 -0800
committerJakub Kicinski <kuba@kernel.org>2024-12-05 11:50:14 -0800
commit302cc446cbd92aadff72a647cebc13d5634f8342 (patch)
tree759fe019d2e1c82ca8590f34c7ba46ab9ddada6e /lib/string.c
parentda4fa00abe5674d3d165cfd8032c740e8aab4d3b (diff)
parent896d8946da97332d4dc80fa1937d8dd6b1c35ad4 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Cross-merge networking fixes after downstream PR (net-6.13-rc2). No conflicts or adjacent changes. Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'lib/string.c')
-rw-r--r--lib/string.c23
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);