The string.h `n' versions aren't for creating C-style strings, but rather for manipulating 0-padded fixed-size buffers. stpncpy is no exception: the destination is padded if the source is smaller (of course, unnecessary for C-style strings), and the destination is not 0-terminated if the source is too large (not a great idea if you're trying to create a C-style string).
Quite why the stdio.h `n' versions do something different, I couldn't say. They should probably have chosen a different letter, as this stuff has been enough of a pitfall for long enough without adding yet another one into the mix. (One option: following the example of BSD-style `strlcpy', as popularized by Ulrich Drepper, `l'. Too late now, of course.)
Yet the vulnerability has absolutely nothing to do with stpcpy() being used.
The problem is alloca() is used to allocate the space stpcpy() is writing into. Using the 'n' variant here wouldn't have made the slightest difference.
stpncpy() is still brain dead for copying null-terminated strings. Regardless of your viewpoint on truncating strings, the zero-pad behavior is wasteful and rarely necessary.
My point stands. C/C++ aren’t memory safe. You can’t just copy stuff around in memory and expect the compiler to fix it for you when the sizes don’t match. This isn’t Python or Node.
I’m seriously curious as to why the non-n versions are still allowed to compile. The dangers seem way too real.
C and C++ give you low level tools, in a variety of senses. For backwards-compatibility reasons, which is a big part of the value of languages like C, C++, Go, and Java, removing anything is difficult or impossible. We barely got rid of gets(3) in C11, which is and has always been impossible to use safely.
In contrast, it is at least possible to use the non-n versions of string routines safely. In addition, the 'n' versions have deleterious side effects that make their adoption unappealing:
* zero padding to n
* no nul termination for strings of length n or longer
The BSD 'l' versions (strlcpy, etc) don't have either of those first two problems, but do have:
* not in standard C, nor POSIX;
* as a result, glibc still refuses to implement them
In addition, some people will inevitably complain that both 'n' and 'l' variants inevitably truncate source strings if they don't fit, and that therefore no one should use either of them, you should just perfectly calculate lengths and use the unchecked ones without making mistakes. I can't tell if these people are delusional or trolling, but realistically, programmers make mistakes, and using unchecked string routines is a common source of buffer overflow; this is usually a worse problem than string truncation.