4 ms·
The point of strlcpy(3) is not to be the world's best and most efficient string copier. It's to provide a drop-in replacement to previous, memory-unsafe string
by EPWN3D 2y ago
The point of strlcpy(3) is not to be the world's best and most efficient string copier. It's to provide a drop-in replacement to previous, memory-unsafe string copy routines in constrained environments where you have to have bounds on stuff and might not have an allocator.
If there are bugs with truncation in the resulting buffer, those are the program's bugs, and they existing before strlcpy(3) came into the picture.
- foobiekr 2y agoThis. I don't understand the objection and I spent 20 years writing C code. The reason to use strlcpy is not to _fix the bug_ but rather _to prevent the bug from turning into a crash, memory corruption, or exploit_. It also forces discipline by carrying around the length. As you say, it's also a drop-in. A truncation bug is a hell of a lot easier to debug than memory corruption.
- rini17 2y ago> It also forces discipline by carrying around the length. LOL. It does not force anything - you can mishandle source or destination buffer lengths very easily and compiler won't say anything. I sometimes wonder what kind of disaster will have to happen to make C programmers agree on a standard buffer (i.e. pointer+size) type with mandatory runtime bounds enforcement ....
- foobiekr 2y agoForce is too strong a word. Yes, it's possible someone just passes whatever, or just passes strlen(s) which is an even dumber answer.
- mafuyu 2y agoI've worked on embedded RTOS projects where we had our own strlcpy implementation - it's fine. Well, I mean, all the str functions suck because C strings, but that's exactly why sticking to a good shared set of idioms and staying organized is so important. And in C, that means manually tagging buffers with their length, no getting around that. Given that, strlcpy is less bug-prone than strncpy, simply due to requiring less lines of code to use correctly per invocation. I think a lot of the confusion in the C string discourse comes from people thinking they should rely on the NULL termination byte for string length. You really shouldn't, and if you have to do it, you need to be extra careful to check all your assertions that it will be properly terminated. Just carry around the length, and bundle it with the pointer in a struct to pass it around when it makes sense. Not the most ergonomic, but it's C, what can ya do.
- eru 2y agoIt's pretty funny that C strings were decided to be NULL terminated in the ancient past for 'convenience', but it turns out you still need to carry the length around anyway.
- mafuyu 2y agoNot to defend C strings too hard, but it does make some sort of sense, IMO. You have to manage all your buffers manually in C, whether they contain a string or not. If you store a string of length 5 in a 10-byte buffer, you still need to manage the 10-byte buffer. Raw pointers kept things very flexible and lightweight when C was created. Nowadays, things like C++ string_view's and Rust str slices handle this for you automatically, but those came around much later and require more sophistication at compile time.
- eru 2y agoYes, but it's not that much more sophistication, because C already supports structs. (Though I'm not sure if the first versions of C already had structs?)
- saagarjha 2y agoThat’s exactly why you shouldn’t be using it: it does a very bad job at that, with behavior basically nobody wants.
- Someone 2y agoBut doing that if you have a large ancient C code base is a lot of work. The reason for the existence of strlcpy isn’t that it is perfect, it’s that it’s the best option with good UX for integration into an existing C code base.
- saagarjha 2y agoIt's not, though. That's the point: the interface it provides is not very good. The API surface for "I have a string here and I want you to put it there but only the first n bytes" is well-defined and can be done in a much better way than what strlcpy does.
- Someone 2y ago> It's to provide a drop-in replacement to previous, memory-unsafe string copy routines Nitpick: it’s not quite a drop-in. Prototypes of these functions are char * strncpy(char *dst, const char *src, size_t num); size_t strlcpy(char *dst, const char *src, size_t num); strncpy(dst, src, num) always returns dst (https://cplusplus.com/reference/cstring/strncpy/ https://cplusplus.com/reference/cstring/strncpy/), which is quite useless, as the caller knew that already. strlcpy(dst, src, num) returns the total length of the string it tried to create (https://www.unix.com/man-page/posix/3/strlcpy/ https://www.unix.com/man-page/posix/3/strlcpy/). Callers can use that to detect that the string didn’t fit the buffer and reallocate a buffer that’s long enough.
- foresto 2y ago> The point of strlcpy(3) is not to be the world's best and most efficient string copier. It's to provide a drop-in replacement to previous, memory-unsafe string copy routines It's not a drop-in replacement, though. Not even if you ignore the different return type. strncpy guarantees that the buffer will be completely overwritten (filling with null chars at the end), while strlcpy will happily leave remnants of whatever was there before. Just dropping in strlcpy wherever strncpy appears can lead to data leaks or inconsistent hashes, for example, depending on how the buffer's contents are used.
- EPWN3D 2y agoThat behavior should be totally irrelevant to code bases that are trying to handle C strings properly. If you have some reliance on the content of the buffer after the terminator, you've for problems that the string copy routine cannot help you with.
- foresto 2y ago> That behavior should be totally irrelevant to code bases that are trying to handle C strings properly. "No true Scotsman..."
- kevin_thibedeau 2y agoIt is a problem when people foolishly dump structs and fixed size buffers to storage without proper serialization. If you need that level of performance then you own the consequences.