Removing strncpy

Document #: N3935
Date: 2026-07-15
Project: Programming Language C
Audience: WG14
Reply-to: Nevin “:-)” Liber
<>

1 Revision History

1.1 N3935

First proposed.

2 Motivation and Scope

strncpy is a terrible, error-prone, memory-unsafe, poorly-named, insecure function. It is long past time we remove it.

2.1 History

It appears to have originated in Version 7 Unix (1979), 46 years ago…

While not in the first edition of The C Programming Language by Brian W. Kernighan and Dennis M. Ritchie (1978), it was added when ANSI C was first standardized:

4.11.2.4 The strncpy function

strncpy was initially introduced into the C library to deal with fixed-length name fields in structures such as directory entries. Such fields are not used in the same way as strings: the trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter names to null assures efficient field-wise comparisons. strncpy is not by origin a “bounded strcpy,” and the Committee has preferred to recognize existing practice rather than alter the function to better suit it to such use.

Rationale for American National Standard for Information Systems — Programming Language — C, §4.11.2.4

2.2 Personal Experience

Back in the early 2000s (long before having lofty aspirations of becoming a member of this committee), this author was debugging a production issue directly caused by the use of strncpy.

The developer who used it didn’t realize:

Because it was so error-prone and the cause of a field issue, the company policy changed to ban the use of strncpy.

2.3 Common Vulnerabilities and Exposures (CVEs)

A simple search finds that strncpy has been the cause of no less than fifteen CVEs:

2.4 Linux Kernel

Most recently (2026-06-19), the Linux kernel has removed strncpy from its codebase. Why? Linus Torvalds wrote in Linux Kernel Commit: strncpy removal:

strncpy() has been removed from the kernel. All former callers have been migrated to safer alternatives.

strncpy() did not guarantee NUL-termination of the destination buffer, leading to linear read overflows and other misbehavior. It also unconditionally NUL-padded the destination, which was a needless performance penalty for callers using only NUL-terminated strings. Due to its various behaviors, it was an ambiguous API for determining what an author’s true intent was for the copy.

3 Design Decisions

3.1 Isn’t this a breaking change?

Yes it is (but it isn’t a quiet change), which means we have to weigh the tradeoff of that against doing nothing. If we continue to leave it in, we know it leads to:

3.2 Why not mitigate it via education?

We’ve had over 4½ decades attempting to educate the world on this. Education hasn’t worked as a general mitigation strategy. There have been endless warnings in compiler diagnostics, static analysis tools, textbooks, coding standards, blog posts and conference talks.

3.3 Why not add a new string type with a safe API?

While that would be nice, that is likely to take years (if not decades), has no guarantee of actually being agreed upon and adopted by the members of WG14, and still doesn’t address this problem, as it will stick around as long as strncpy is a WG14-blessed function.

Specifically:

3.4 We could just deprecate it.

We could, but that is a weak choice. How many more years/decades should WG14 ignore that this has been a real world problem for decades that should be addressed?

We are not lacking evidence that this function should be removed; the only thing lacking is our willingness to act on it.

3.5 Shouldn’t we deprecate it and replace it with something better?

Again, that would be nice, but really isn’t much different than the problems we have introducing a new string type.

The Linux Kernel replaced strncpy with seven different functions:

How long would it take WG14 to agree on something similar? Certainly not in time for C29.

I’m not saying we shouldn’t pursue a replacement (we should), but we shouldn’t wait for it. Perfect is the enemy of good.

3.6 Is this just a token effort?

This is a small, achievable step, which is its value.

3.7 Implementors will keep it around anyway.

3.8 We have precedent with gets.

gets was removed, and the sky did not fall. All the concerns about breaking existing code (it did), education, what implementations would do, etc., were valid but ultimately proved to be manageable.

3.9 What about strncpy_s?

It is out of scope for this proposal, as it does not share the same defects as strncpy.

The status of Annex K is an independent question that should be evaluated on its own merits.

4 Proposed Wording

All edits are relative to N3886.

4.1 Modify §7.28.2 [Copying functions]

In §7.28.2, remove subclause 5:

7.28.2.5 The strncpy function

Synopsis

#include <string.h>
char *strncpy(char * restrict s1, const char * restrict s2, size_t n);

Description

The strncpy function copies not more than n characters (characters that follow a null character are not copied) from the array pointed to by s2 to the array pointed to by s1.329) If the array pointed to by s2 is a string that is shorter than n characters, null characters are appended to the copy in the array pointed to by s1, until n characters in all have been written.

Returns

The strncpy function returns the value of s1.

Remove footnote 329:

329) Thus, if there is no null character in the first n characters of the array pointed to by s2, the result will not be null-terminated.

4.2 Modify §B.27 [String handling <string.h>]

Remove the following declaration:

char *strncpy(char * restrict s1, const char * restrict s2, size_t n);

4.3 Modify §M.2 [Changes from previous revisions]

Add the following bullet to the list of changes:

The strncpy function has been removed.

4.4 Modify the Index

Remove the entry for strncpy.

5 Conclusion

strncpy may have been a reasonable function for PDP-11 directory entries in 1979. It is not a reasonable function for a security-conscious world in 2026, let alone 2029.

The cost of removal is a compiler error and a one-time code change. The cost of inaction is measured in CVEs.

When the committee removed gets, it established a principle: the standard should not endorse functions that are known to cause systematic harm. strncpy meets that bar. The principle should be applied consistently.

6 Acknowledgements

Nevin Liber was supported by the Office of Science, U.S. Department of Energy, under contract DE-AC02-06CH11357.

All the (non-quoted) ideas are mine or based on discussions, but I did use Claude Opus 4.6 and a thesaurus to inspire more compelling ways to phrase and present them.

7 References