Live data from Hacker News

No strcpy either

daniel.haxx.se

71–80 of 151 posts

Re: No strcpy either

#71
post #47

Earlier quoted context omitted.

strncpy is fairly easy, that's a special-purpose function for copying a C string into a fixed-width string, like typically used in old C applications for on-disk formats. E.g. you might have a char username[20] field which can contain up to 20 characters, with unused characters filled with NULs. That's what strncpy is for. The destination argument should always be a fixed-size char array. A couple years ago we got a…

Isn't strlcpy the safer solution these days?

I don't think anybody in this thread read the article.

Strlcpy tries to improve the situation but still has problems. As the article points out it is almost never desirable to truncate a string passed into strXcpy, yet that is what all of those functions do. Even worse, they attempt to run to the end of the string regardless of the size parameter so they don't even necessarily save you from the unterminated string case. They also do loads of unnecessary work, especially if your source string is very long (like a mmaped text file).

Strncpy got this behavior because it was trying to implement the dubious truncation feature and needed to tell the programmer where their data was truncated. Strlcpy adopted the same behavior because it was trying to be a drop in replacement. But it was a dumb idea from the start and it causes a lot of pain unnecessarily.

The crazy thing is that strcpy has the best interface, but of course it's only useful in cases where you have externally verified that the copy is safe before you call it, and as the article points out if you know this then you can just use memcpy instead.

As you ponder the situation you inevitably come to the conclusion that it would have been better if strings brought along their own length parameter instead of relying on a terminator, but then you realize that in order to support editing of the string as well as passing substrings you'll need to have some struct that has the base pointer, length, and possibly a substring offset and length and you've just re-invented slices. It's also clear why a system like this was not invented for the original C that was developed on PDP machines with just a few hundred KB of RAM.

Is it really too late for the C committee to not develop a modern string library that ships with base C26 or C27? I get that they really hate adding features, but C strings have been a problem for over 50 years now, and I'm not advocating for the old strings to be removed or even deprecated at this time. Just that a modern replacement be available and to encourage people to use them for new code.

Re: No strcpy either

#72
post #48

Earlier quoted context omitted.

Until you pass them as a `char *` by accident and it eventually makes its way to some code that does expect null termination. There’s languages where you can be quite confident your string will never need null termination… but C is not one of them.

You don’t do that by accident. Fixed-width strings are thoroughly outdated and unusual. Your mental model of them is very different from regular C strings.

The mental model doesn’t matter, it’s the compiler’s model that is going to bite you. If the compiler doesn’t reject it, it will happen eventually.

Re: No strcpy either

#73
post #48

Earlier quoted context omitted.

Until you pass them as a `char *` by accident and it eventually makes its way to some code that does expect null termination. There’s languages where you can be quite confident your string will never need null termination… but C is not one of them.

You don’t do that by accident. Fixed-width strings are thoroughly outdated and unusual. Your mental model of them is very different from regular C strings.

Sadly, all the bug trackers are full of bugs relating to char*. So you very much do those by accident. And in C, fixed width strings are not in any way rare or unusual. Go to any c codebase you will find stuff like:

   char buf[12];
   sprintf(buf, "%s%s", this, that); // or
   strcat(buf, ...) // or
   strncpy(buf, ...) // and so on..

Re: No strcpy either

#74
post #62
post #53

It's worth noting that strcpy() isn't just bad from a security perspective, on any CPU that's not completely ancient it's bad from a performance perspective as well. Take the best case scenario, copying a string where the precise length is unknown but we know it will always fit in, say, 64 bytes. In earlier days, I would always have used strcpy() for this task, avoiding the "wasteful" extra copies memcpy() would make…

We should just move away from null-terminated strings, where we can, as fast as we can.

We have. C is basically the only langage in any sort of widespread use where terminated strings are a thing.

Which of course causes issues when languages with more proper strings interact with C but there you go.

Re: No strcpy either

#75
post #70
post #18

I've always wondered at the motivatons of the various string routines in C - every one of them seems to have some huge caveat which makes them useless. After years I now think it's essential to have a library which records at least how much memory is allocated to a string along with the pointer. Something like this: https://github.com/msteinert/bstring

> I've always wondered at the motivatons of the various string routines in C This idiom: char hostname[20]; ... strncpy( hostname, input, 20 ); hostname[19]=0; exists because strncpy was invented for copying file names that got stored in 14-byte arrays, zero terminated only if space permitted ( https://stackoverflow.com/a/1454071 )

Technically strncpy was invented to interact with null-padded fixed-size strings in general. We’ve mostly (though not entirely) moved away from them but fixed-size strings used to be very common. You can see them all over old file formats still.

Re: No strcpy either

#76
post #57

"strncpy() is a weird function with a crappy API." Well if you bother looking up that it's originally created for non null-terminated strings, then it kinda makes sense. The real problem begun when static analyzers started to recommend using it instead of strcpy (the real alternative used to be snprintf, now strlcpy).

strlcpy is a BSD-ism that isn't in posix. The official recommendation is stpecpy. Unfortunately, it is only implemented in the documentation, but not available anywhere unless you roll your own:

https://man7.org/linux/man-pages/man7/string_copying.7.html

Re: No strcpy either

#77
post #51

Earlier quoted context omitted.

As long as the number of people newly being convinced that AI generated bounty demands are a good way to make money equals or exceeds the number of people realising it isn't and giving up, the problem remains. Not helped, I imagine, that once you realise it doesn't work, an easy pivot is to start convincing new people that it'll work if they pay you money for a course on it.

Apparently FOSS developers have been getting this kind of slop report even though they clearly don't offer a bug bounty.

There are no shortage of people wanting to be able to say they found CVE-XXXX-XXX or a bug in product X.

Re: No strcpy either

#78
post #47

Earlier quoted context omitted.

Isn't strlcpy the safer solution these days?

I don't think anybody in this thread read the article. Strlcpy tries to improve the situation but still has problems. As the article points out it is almost never desirable to truncate a string passed into strXcpy, yet that is what all of those functions do. Even worse, they attempt to run to the end of the string regardless of the size parameter so they don't even necessarily save you from the unterminated string ca…

Do they really need to at this point? Just include bstrlib and stop thinking about it?

Re: No strcpy either

#79
post #53

It's worth noting that strcpy() isn't just bad from a security perspective, on any CPU that's not completely ancient it's bad from a performance perspective as well. Take the best case scenario, copying a string where the precise length is unknown but we know it will always fit in, say, 64 bytes. In earlier days, I would always have used strcpy() for this task, avoiding the "wasteful" extra copies memcpy() would make…

I haven't seen a strcpy use a scalar loop in ages. Is this an ARM thing?

Re: No strcpy either

#80

Earlier quoted context omitted.

I don't think anybody in this thread read the article. Strlcpy tries to improve the situation but still has problems. As the article points out it is almost never desirable to truncate a string passed into strXcpy, yet that is what all of those functions do. Even worse, they attempt to run to the end of the string regardless of the size parameter so they don't even necessarily save you from the unterminated string ca…

Do they really need to at this point? Just include bstrlib and stop thinking about it?

Having an official replacement is the only thing that I think will motivate the majority C programmers to finally switch.
Post reply on HN