Live data from Hacker News

Stop using strncpy already (2013)

randomascii.wordpress.com

51–60 of 83 posts

Re: Stop using strncpy already (2013)

#51

Earlier quoted context omitted.

Well, again, you have to assume that the caller called you right, i.e. that the pointer you were passed points to a buffer with exactly one zero in it, at the end. Furthermore, unless there's also a (potentially wrong) length argument, you have to read every byte of the destination buffer while you're copying and stop when you see a zero. There's a lot to be said for a reimplementation like bstrlib that wraps char ar…

I am not sure I follow the extent of the problem. With `strncpy`, the caller assumes the responsibility of buffer size (by specify that size explicitly every single time. I thought that responsibility is not being debated within the current context.

That responsibility - for passing the correct buffer size - is one of the issues. I have seen many bugs where the caller simply passed the wrong size to strncpy. If you have a fixed-size buffer then the compiler can infer the size for you, thus making this class of bugs go away entirely.

TL;DR - I've reviewed enough code to know that software developers pass the wrong size to strncpy and friends.

Re: Stop using strncpy already (2013)

#52
post #8

strncp is fine, however it was never meant for null-terminated strings! A safe alternative is using snprintf and checking the return value for truncation.

snprintf is hardly safe. It does guarantee null termination, so that is progress, but it requires the caller to pass the buffer size. As I mention in the "More typing means more errors" section of the article software developers are endlessly creative about ways to pass the wrong buffer size. They usually pass the right buffer size, but 99.9% correct still means a lot of bugs. These bugs can be avoided by using a template function to infer the destination buffer size. A template wrapper around snprintf would work very nicely.

Re: Stop using strncpy already (2013)

#53

Earlier quoted context omitted.

I am not sure I follow the extent of the problem. With `strncpy`, the caller assumes the responsibility of buffer size (by specify that size explicitly every single time. I thought that responsibility is not being debated within the current context.

That responsibility - for passing the correct buffer size - is one of the issues. I have seen many bugs where the caller simply passed the wrong size to strncpy. If you have a fixed-size buffer then the compiler can infer the size for you, thus making this class of bugs go away entirely. TL;DR - I've reviewed enough code to know that software developers pass the wrong size to strncpy and friends.

So you need a data structure (or language) that have size embedded in, and the knowledge (and restrictions) of that data structure need to spread to every libraries or function that one use (we are talking about string handling here). It appears to me that you have cornered yourself that the only solution is to modify C/C++ standards to redefine string handling.

I am not saying that is bad. But solutions already exist. One is using the string class, another being transiting to a dynamic language (having size as part of data structure and checking it at every usage is one step into dynamic types).

Alternatively, the compiler can take over this responsibility by statically check every call (the rust solution). That is a different language. On that, I have a question: how can we pass the syntactic buffer size into a static library without embedding the size into the data? If we do embedding the size, then it is still dynamic within the context of the library.

Either way, one should not still be discussing the safety of strncpy here.

Now as long as we are discussing strncpy, I assume it is given that we do not want to have buffer size as permanent part of the simple string type and we are not looking for any solutions that demand an overhaul of the language/libraries. I assume it is given that caller takes the responsibility of buffer size -- exchange with a bit responsibility for simpler system and greater control.

You won't have a good solution (or good discussions) without confining our context first.

Re: Stop using strncpy already (2013)

#54
post #14

I don’t understand why silently truncating strings is considered to be acceptable practice. If you have the length of both, simply assert the length of the destination is <= the length of the source. Problem solved (bugs become obvious in testing).

The more I think about this, the more sense it makes to say you should check the length of the buffer before they copy. I'm not sure an assert is always right, exactly what should be done if the string doesn't fit may depend on what the program is doing. But silently truncating is generally not the right thing to do.

Re: Stop using strncpy already (2013)

#55
post #16

Earlier quoted context omitted.

How is that a good thing? There are ways of abstracting/handling strings that are strictly safer than other ways. In an unsafe language like C, you're inviting problems by trying to do things in your own idiosyncratic way.

Sometimes performance or flexibility are important concerns. But feel free to manage millions of small strings with std::string or even as GC'ed objects :). And incur the overhead of indirection when attaching bounded-size strings to other data.

Defaults are important. C++ provides a much safer string type as default and let's programmers do their own thing in case it doesn't work for their use case (I'd try providing a different allocator before writing a different string type tbh). C on the other hand doesn't really provide a string type at all and forces everyone to start by writing a string library if they don't want to hunt buffer overflows until hell freezes over.

Re: Stop using strncpy already (2013)

#56
post #55

Earlier quoted context omitted.

Sometimes performance or flexibility are important concerns. But feel free to manage millions of small strings with std::string or even as GC'ed objects :). And incur the overhead of indirection when attaching bounded-size strings to other data.

Defaults are important. C++ provides a much safer string type as default and let's programmers do their own thing in case it doesn't work for their use case (I'd try providing a different allocator before writing a different string type tbh). C on the other hand doesn't really provide a string type at all and forces everyone to start by writing a string library if they don't want to hunt buffer overflows until hell f…

[deleted]

Re: Stop using strncpy already (2013)

#57
post #46

Earlier quoted context omitted.

Sometimes performance or flexibility are important concerns. But feel free to manage millions of small strings with std::string or even as GC'ed objects :). And incur the overhead of indirection when attaching bounded-size strings to other data.

Rust manages to do it just fine...

How?

Re: Stop using strncpy already (2013)

#58

Earlier quoted context omitted.

That responsibility - for passing the correct buffer size - is one of the issues. I have seen many bugs where the caller simply passed the wrong size to strncpy. If you have a fixed-size buffer then the compiler can infer the size for you, thus making this class of bugs go away entirely. TL;DR - I've reviewed enough code to know that software developers pass the wrong size to strncpy and friends.

So you need a data structure (or language) that have size embedded in, and the knowledge (and restrictions) of that data structure need to spread to every libraries or function that one use (we are talking about string handling here). It appears to me that you have cornered yourself that the only solution is to modify C/C++ standards to redefine string handling. I am not saying that is bad. But solutions already exis…

You're quite right, it's important to set the context. But no matter what context you pick, your choice is costly:

* We're going to stick with C and its standard library: lots of room to continue to make errors.

* We're going to stick with C, but it's OK to consider an alternate implementation of strings: the C standard, the standard library, and lots of other C libraries are full of functions that deal in char* strings, so you're stuck with them. Also, runtime overhead increases.

* We're willing to consider other languages: other languages have compiler overhead, semantic overhead, runtime overhead, or all three. Also, you still have to interoperate with C.

Re: Stop using strncpy already (2013)

#59

Earlier quoted context omitted.

Well, again, you have to assume that the caller called you right, i.e. that the pointer you were passed points to a buffer with exactly one zero in it, at the end. Furthermore, unless there's also a (potentially wrong) length argument, you have to read every byte of the destination buffer while you're copying and stop when you see a zero. There's a lot to be said for a reimplementation like bstrlib that wraps char ar…

I am not sure I follow the extent of the problem. With `strncpy`, the caller assumes the responsibility of buffer size (by specify that size explicitly every single time. I thought that responsibility is not being debated within the current context.

> I thought that responsibility is not being debated within the current context

I bring it up because the article makes programming errors on the part of the caller part of the case for its "safe" solution.

Re: Stop using strncpy already (2013)

#60
post #16

Earlier quoted context omitted.

How is that a good thing? There are ways of abstracting/handling strings that are strictly safer than other ways. In an unsafe language like C, you're inviting problems by trying to do things in your own idiosyncratic way.

Sometimes performance or flexibility are important concerns. But feel free to manage millions of small strings with std::string or even as GC'ed objects :). And incur the overhead of indirection when attaching bounded-size strings to other data.

Apparently IBM and Unisys mainframe systems programming languages did just fine.
Post reply on HN