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 the ANSI C Programming Language, 1990
Because nobody reads the manual for strncpy, they just use it and assume it does what they want (nope) and then reimplement it based on that same misunderstanding.
This worked perfectly fine in the kernel. It only broke when it interacted with bpftrace hashmaps which apparently was a use case that hadn’t been considered when it was written. bpf in the kernel is fairly new so it’s not that surprising that the interaction wasn’t foreseen.
Why do they call it
strncpyif it does something else?Rationale for the ANSI C Programming Language, 1990
Sorry, I read that as “why doesn’t
strncpydo something resemblingstrcpy?” not “why doesn’t kernelstrncpydostrncpy?”Because nobody reads the manual for strncpy, they just use it and assume it does what they want (nope) and then reimplement it based on that same misunderstanding.
I guess it was bold to assume kernel devs know the dangers of C programming. :<
This worked perfectly fine in the kernel. It only broke when it interacted with bpftrace hashmaps which apparently was a use case that hadn’t been considered when it was written. bpf in the kernel is fairly new so it’s not that surprising that the interaction wasn’t foreseen.
Reading the description in the post, it sounds like
do_strncpy_from_useris closer to strlcpy than strncpy, and wasn’t padding the buffer with zero.What’s worse than the behavior of strncpy? Calling your function
my_strncpywithout implementing the behavior of strncpy.