On Mon, 05 Feb 2018 14:21:07 +0000 Ralph Corderoy <firstname.lastname@example.org> wrote:
Ralph Corderoy writes:
I'd be quite surprised if we don't have at least one off-by-one error
Separate from those errors, a lot of the code doesn't care if the char
ends up unterminated and continue to use the result assuming it is.
IOW, it assumes the char is `big enough', and at 8 KiB it often is.
There was a long `strncpy(3), die, die, die.' thread back in 2016 about
this, including that strncpy() pads to the full 8 KiB with NULs. My
to-do list summarises what I think was the conclusion.
- Add trunccpy() for when truncation is correct, e.g. the start of a
long string back to the user in an error message. [Done.]
void trunccpy(char *dst, const char *src, size_t size);
/* A convenience for the common case of dst being an array. */
#define TRUNCCPY(dst, src) trunccpy(dst, src, sizeof (dst))
- Add uvstrncpy(), an `unvetted' strncpy() that dies or warns when
truncation occurs and always ensures the destination is
NUL-terminated. The choice of death, warning, or silence is at
- Add strpadcpy() that gives strncpy()'s truncating, padding,
- Replace all strncpy() with uvstrncpy().
- Examine the unvetted uvstrncpy() and replace with one of the
The global search/replace of strncpy() is going to mess up
cherry-picking, folks' unpushed commits, etc., so I've avoided doing it,
but it looks like GCC 8.0, when it's released, might force the issue.
As for the related snprintf(), etc., well, at least destination is NUL
terminated, even if the truncation could cause data loss. They too need
looking at and replacing in time.
Have you guys considered using the Boehm-Demers-Weiser
conservative GC? Then you can just use strdup(), strndup(),
asprintf(), replace char vars with char* vars and let the
garbage collector worry about cleaning things up. Seems much
simpler than adding functions such as uvstrncpy, turnccpy.
trunccpy() is strndup().
Go-1.0 used a conservative GC and it was fast enough. Also
note Go strings are variable sized.