strncpy will produce different results for an empty string depending on the
preceding value of dst:
char buf[4];
bzero(buf, sizeof(buf));
buf[0] = 0;
buf[1] = 9;
strncpy(&buf[1], "", 3);
"clen" will be 0 since strnlen("") is 0, which will then look into dst[-1]
(buf[0]) to decide if it terminates dst or not.
Instead of working around, replace strncpy for a conformant version, taken
from OpenBSD libkern, as a bonus we zero out the remaining buffer.
https://github.com/openbsd/src/blob/master/sys/lib/libkern/strncpy.c
Signed-off-by: Christiano Haesbaert <haesbaert@haesbaert.org>
Reviewed-by: Eduard-Florin Mihailescu <mihailescu.eduard@gmail.com>
Approved-by: Simon Kuenzer <simon@unikraft.io>
GitHub-Closes: #973
char *strncpy_isr(char *dst, const char *src, size_t len)
{
- size_t clen;
-
- clen = strnlen_isr(src, len);
- memcpy_isr(dst, src, clen);
+ if (len != 0) {
+ char *d = dst;
+ const char *s = src;
+
+ do {
+ if ((*d++ = *s++) == 0) {
+ /* NUL pad the remaining n-1 bytes */
+ while (--len != 0)
+ *d++ = 0;
+ break;
+ }
+ } while (--len != 0);
+ }
- /* instead of filling up the rest of left space with zeros,
- * append a termination character if we did not copy one
- */
- if (clen < len && dst[clen - 1] != '\0')
- dst[clen] = '\0';
return dst;
}
char *strncpy(char *dst, const char *src, size_t len)
{
- size_t clen;
-
- clen = strnlen(src, len);
- memcpy(dst, src, clen);
+ if (len != 0) {
+ char *d = dst;
+ const char *s = src;
+
+ do {
+ if ((*d++ = *s++) == 0) {
+ /* NUL pad the remaining n-1 bytes */
+ while (--len != 0)
+ *d++ = 0;
+ break;
+ }
+ } while (--len != 0);
+ }
- /* instead of filling up the rest of left space with zeros,
- * append a termination character if we did not copy one
- */
- if (clen < len && dst[clen - 1] != '\0')
- dst[clen] = '\0';
return dst;
}