5 ms·
The article is literally false. strncpy is safer than strcpy. The argument of the author is it still has room for abuse.
by gonmf 9y ago
The article is literally false. strncpy is safer than strcpy. The argument of the author is it still has room for abuse.
- Gracana 9y agoWhen it fails it leaves you with something that's not a string. It's not safe and it's not a strcpy().
- mikeash 9y agoWhen strcpy fails it results in undefined behavior. strncpy is safer. It is not safe. This article really ought to apply s/safer/safe/ and then it'll all be good.
- geofft 9y agoWhen strncpy fails it leaves you with a character array that isn't NUL-terminated. Passing that to another string-handling function is undefined behavior, because it is not a string.
- mikeash 9y agoRight, so you need to make two mistakes before you get undefined behavior with strncpy, and only one mistake to get it with strcpy. Thus, safer, but not safe.
- sirclueless 9y agoI don't agree. Any input string that violates the strcpy invariants (must be a valid null-terminated string with length <= destination buffer size) will also violate the strncpy invariants if you subsequently treat the destination buffer as a string. Since treating the destination buffer as a string is very tempting to do given that it came from a function named "str*cpy()", you've basically added another "Gotcha" to strcpy() without gaining any safety. You're basically trading one form of undefined behavior that's explicit in strcpy for another form of undefined behavior when a developer mishandles the return value of strncpy.
- mikeash 9y agoI don't get how that adds another gotcha. The scenarios in which strncpy gets you are a strict subset of the scenarios in which strcpy gets you.
- taeric 9y agoIt is the passing of the string that is undefined. You know exactly what you get from strncpy. If you thought it did something else, you were wrong. But it is fully defined. This would be like claiming that malloc is unsafe because it doesn't return a null terminated string.
- dllthomas 9y ago> This would be like claiming that malloc is unsafe because it doesn't return a null terminated string. Well, no, because this behavior is very close to the more commonly desired behavior and often indistinguishable therefrom. That makes it more of a "gotcha".
- dom0 9y agoThat's the difference between bad API design and good API design. strncpy is bad. But so are many APIs that originated in a time where arrays were zero-indexed to save one or two instructions in a compiler. (Though these are a bit younger)
- dllthomas 9y ago> That's the difference between bad API design and good API design. strncpy is bad. But so are many APIs Agreed. > arrays were zero-indexed to save one or two instructions in a compiler Actually, I find zero-indexing more consistent whenever you need to do math with the indexes.
- taeric 9y agoIs it? I expect there are many that think they can malloc a string and immediately pass it to a function to play with. I've seen it done, back when I was a TA. And thinking that strncpy will enforce a null at the end actually seems nonsensical to me. Now. I agree that it may not have at some point in my life. But this is again arguing that it is not safer than strcpy. It most certainly is. Just not completely safe. Which again, is no surprise. Why not point out that it does no checking that you passed it pointers you are allowed to write into? I mean, I get that mistakes can be made. I even agree it is not safe. However, to claim it is not safer is akin to the people that claim Java is not safer than C because example.
- mjevans 9y agoYou called it wrong. It's a primitive and gives you choices. You can either: A) call it with sizeof(target) - 1 to explicitly tell it to NOT over-write the guard byte at the end, OR B) you can add an explicit operation to always over-write the byte at the end
- ori_b 9y agoStrncpy does not return a valid string. It is not a substitute for strcpy. Take the strlcpy() function from OpenBSD and incorporate that into your source if you don't have access. Strlcpy() is a well designed substitute for strcpy.
- geofft 9y agoExcerpting from the article: > Now having a function like this in the standard library isn't such a bad thing in itself. It's designed to deal with a specialized data structure ... > The problem is that the name strncpy() strongly implies that it's a "safer" version of strcpy(). It isn't. .... > It's because strncpy()'s name implies something that it isn't that it's such a trap for the unwary. It's not a useless function, but I see far more incorrect uses of it than correct uses. This article is my modest attempt to spread the word that strncpy() isn't what you probably think it is. This argument seems correct to me. "Safer," here, does not mean "If you swap out every use of strcpy for a correct use of strncpy, you'll have fewer bugs." As the author is defining it, "safer" includes the risk that someone will be less rigorous with their code by assuming strncpy will solve all their problems. It won't. It will solve some of their problems, yes, but they still have to analyze their problem almost as rigorously as if they were using strcpy. If a code reviewer cares deeply about strcpy and less deeply about strncpy (and anecdotally this is a thing code reviewers do), then in practice, the use of strncpy is not safer.
- dllthomas 9y agoActually, I think it's true that "If you swap out every use of strcpy for a correct use of strncpy, you'll have fewer bugs." Any use of strncpy that breaks would also have broken if strcpy had been used instead, and there exist some situations where strncpy would not break while strcpy would; for instance, if we just inspect a prefix of the resulting string. That said, it's certainly the case that most breaking uses of strcpy, if naively replaced with strncpy, still break.
- geofft 9y ago> Actually, I think it's true that "If you swap out every use of strcpy for a correct use of strncpy, you'll have fewer bugs." Yes, I agree that this statement is true. But my claim is that this is not what the article means by "safer", and the article's definition of "safer" is more useful. That is, people who are saying "The article is wrong because it is possible to use strncpy correctly in cases where strcpy was not being used correctly" are not disagreeing with the article so much as talking past it.
- dnautics 9y agoYou should read the article. The issue is not that strncpy is not safer, the issue is that strncpy is not a string operation, but a memory operation
- mjevans 9y agoOnly it isn't. strncpy will /terminate/ at the end of the string if it's shorter than the allocated buffer. If, somehow, the source string is invalid it will then terminate at the specified cutoff point. However one should argue that if it has overflowed bounds, that if the source isn't a valid string, you've already violated the contract of a secure environment and thus something has gone wrong and should be handled at a level higher than string copy preferences. Use of strncpy, however, assumes that the source string /is/ valid, but might overflow the target buffer. In /that/ case truncation may be desired and if not the program flow reacting accordingly is probably desired. (This is C, you don't /throw/ errors, you write explicit paths.)