News for hackers. Stuff that matters.
Re:Everything I wish I knew when learning C by unwind on Monday November 28, 2022 @08:32AM (#33773408)
This looks decent, but I'm (highly) opposed to recommending `strncpy()` as a fix for `strcpy()` lacking bounds-checking. That's not what it's for, it's weird and should be considered as obosolete as `gets()` in my opinion.

If available, it's much better to do the `snprintf()` way as I mentioned in a comment last week, i.e. replace `strcpy(dest, src)` with `snprintf(dst, sizeof dst, "%s", src)` and always remember that "%s" part. Never put src there, of course.

There's also `strlcpy()` on some systems, but it's not standard.

Re:Everything I wish I knew when learning C by masklinn on Monday November 28, 2022 @08:54AM (#33773654)
strncpy does have its odd and rare use-case, but 100% agree that it is not at all a “fix” for strcpy, it’s not designed for that purpose, and unsuited to it, being both unsafe (does not guarantee NUL-termination) and unnecessary costly (fills the destination with NULs).

The strn* category was generally designed for fixed-size NUL-padded content (though not all of them because why be coherent?), the entire item is incorrect, and really makes the entire thing suspicious.

Re:Everything I wish I knew when learning C by AstralStorm on Monday November 28, 2022 @09:23AM (#33773930)
Then there are strn*_s since C11 (and available before that on many platforms) which do exactly what you want.
Re:Everything I wish I knew when learning C by masklinn on Monday November 28, 2022 @09:40AM (#33774128)
Lol no. These are the Annex K stuff which Microsoft got into the standard, which got standardised with a different behaviour than Windows’ (so even on windows following the spec doesn’t work) and which no one else wants to implement at all.

And they don’t actually “do exactly what you want”, see for instance N1967 (“field experience with annex k”) which is less than glowing.

Re:Everything I wish I knew when learning C by mtlmtlmtlmtl on Monday November 28, 2022 @09:40AM (#33774122)
>sizeof dst

Note that this only works if dst is a stack allocated(in the same function) array and not a char *

Re:Everything I wish I knew when learning C by unwind on Monday November 28, 2022 @12:05PM (#33776152)
Yes it should be read as a placeholder for whatever you need to do.

Could be an array inside a struct too for instance, that is quite common.

Re:Everything I wish I knew when learning C by sedatk on Monday November 28, 2022 @04:03PM (#33779596)
> and always remember that "%s" part. Never put src there, of course

> Note that this only works if dst is a stack allocated array

Even this "ideal" solution is full of pitfalls. The state of memory safety is so sad in the world of C.

Re:Everything I wish I knew when learning C by tmewett on Monday November 28, 2022 @10:27AM (#33774762)
Ah, that was one of my less considered additions - thank you for the feedback!
Re:Everything I wish I knew when learning C by 0xbadcafebee on Monday November 28, 2022 @12:41PM (#33776680)
Would it be a sin to use memcpy() and leave things like input validation to a separate function?
Re:Everything I wish I knew when learning C by masklinn on Monday November 28, 2022 @02:01PM (#33777966)
If you really need a fast strcpy then probably not, but in most situations snprintf will do the job just fine. And will prevent heartache.
Re:Everything I wish I knew when learning C by unwind on Monday November 28, 2022 @05:04PM (#33780524)
Uh, isn't using `memcpy()` to copy strings doing exactly that?

The problem is that `memcpy()` doesn't know about (of course) string terminators, so you have to do a separate call to `strlen()` to figure out the length, thus visiting every character twice which of course makes no sense at all (spoken like a C programmer I guess ... since I am one).

If you already know the length due to other means, then of course it's fine to use `memcpy()` as long as you remember to include the terminator. :)

Re:Everything I wish I knew when learning C by 0xbadcafebee on Monday November 28, 2022 @07:53PM (#33782208)
The reason you would want to use memcpy would be if 1) you already know what the length is, 2) if you need a custom validator for your input, 3) you don't want to validate your input (however snprintf() is doing that), 4) if the string may include nulls or there is no null terminator.

But the fifth reason may be that depending on snprintf as your "custom-validator-and-encoder-plus-null-terminator" may introduce subtle bugs in your program if you don't know exactly what snprintf is doing under the hood and what its limitations are. By using memcpy and a custom validator, you can be more explicit about how data is handled in your program and avoid uncertainty.

(by "validate" I mean handle the data as your program expects. this could be differentiating between ASCII/UTF-8/UTF-16/UTF-32, adding/preserving/removing a byte-order mark, eliminating non-printable characters, length requirements, custom terminators, or some other requirement of whatever is going to be using the new copy of the data)

Re:Everything I wish I knew when learning C by saagarjha on Tuesday November 29, 2022 @05:51AM (#33785980)
snprintf is pretty slow, partly because it returns things people typically don't want.