flawopen.com/Memory Safety/strcpy vs strncpy
Is strncpy() safer than strcpy()?
A fixed-width field is like a row of labeled slots: the final slot must hold an end marker if later code will treat the bytes as a C string. strncpy() writes at most n bytes, so it avoids a destination overrun only when n is no larger than the real buffer. If the source fills that limit, it adds no null terminator. A later string function can then read beyond the destination looking for the missing marker.
char dst[16]; /* 1. Unbounded — classic overflow */ strcpy(dst, src); /* 2. Bounded, but may not terminate. If strlen(src) >= 16, dst has no '\0' and every later strlen/printf reads out of bounds. */ strncpy(dst, src, sizeof(dst)); /* 3. Off-by-one: room for 16 chars plus a terminator = 17 bytes, but dst only holds 16. */ strncpy(dst, src, sizeof(dst)); dst[sizeof(dst)] = '\0'; /* OOB! */
char dst[16]; /* Preferred: snprintf always null-terminates (when size > 0), and tells you about truncation. */ int n = snprintf(dst, sizeof(dst), "%s", src); if (n < 0 || (size_t)n >= sizeof(dst)) { /* truncated — handle it */ return ERR_TOO_LONG; } /* Or strlcpy where available — always terminates, returns the length it tried to create. */ if (strlcpy(dst, src, sizeof(dst)) >= sizeof(dst)) { return ERR_TOO_LONG; }
What strncpy was actually designed for
Its behavior is not a defect: strncpy() was designed for fixed-width, null-padded character sequences, not as a generally safe C-string copy. If the source string is shorter than n, it pads the destination with null bytes through byte n - 1. If there is no null byte in the first n source bytes, it copies exactly n bytes and does not terminate the destination. That can suit a fixed-width field format; it is hazardous when the result is passed to APIs that expect a null-terminated string.
When the source is shorter than n, the required null padding writes through the full field width. For a large destination and short source, this can do more work than a string-copy routine that stops at the terminator.
Always check for truncation
Preventing the overflow is only half the job. Silent truncation is itself a security problem: a truncated hostname, path, or authorization value can change meaning rather than simply being shorter. snprintf returns the length it wanted to write, so comparing that against the buffer size detects truncation — the same return-value semantics that, when misread as "bytes written", produced Citrix Bleed.
FAQ
They null-terminate and check bounds, which addresses the problem, but portability is uneven — they are well supported on Windows and patchily implemented elsewhere. If you target multiple platforms, snprintf is the dependable choice.
It originated in OpenBSD and is widely available on BSD and macOS, with glibc adding it comparatively recently. Check availability for your targets rather than assuming it.
Prefer std::string and std::string_view, which manage length for you and remove the entire class of bug. Reach for the C functions only at an API boundary that requires a raw buffer.