On Tue, Sep 06, 2016 at 01:10:36PM +0200, Vincent Lefevre wrote: > On 2016-09-05 19:07:18 -0500, Derek Martin wrote: > > On Mon, Sep 05, 2016 at 10:32:40AM -0500, Derek Martin wrote: > > > Is strfcpy() widely available? > > > > Ah, now I see that strfcpy() is a Mutt-specific macro that intends to > > make strncpy() safer. I was actually thinking of strlcpy(), which is > > equivalent to Mutt's strfcpy(); but it does not matter. ALL of these > > functions suffer from the same affliction: If dest is too small, they > > all silently lose data on copy. > > The strfcpy macro looks awful:
Firstly, I'll note that, given the existing macros don't seem to have
caused anyone any grief, the exact macro syntax is largely an academic
consideration. =8^) But I like those discussions, so I'll blather on
a bit about it:
> # define strfcpy(A,B,C) strncpy(A,B,C), *(A+(C)-1)=0
Ah, that's not the definition I saw, but it turns out it's defined in
several places, with two different definitions. The other one is in
rfc822.c:
rfc822.c:#define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}}
Note the block syntax, similar to what I used. At least on GCC, this
does not cause compilation problems in the vast majority of cases,
including the one you highlighted, though I can't say how other
compilers might treat it, or guess what cases I might be missing...
For instance, with gcc the following program (which is basically an
expansion of the macro syntax I suggested) compiles and runs fine,
even with -Wall -Werror:
-=-=-=-=-=-=-=-=-
$ cat blah.c
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc > 0){
{ printf("argc is %d\n", argc); };
} else {
{ printf("argc is not greater than zero\n"); };
}
return 0;
}
$ gcc -Wall -Werror -o blah blah.c
$ ./blah
argc is 1
-=-=-=-=-=-=-=-=-
I seem to recall that I once ran into a situation where the loop
construct you suggested caused a problem, though I can't recall the
details, and seems to me it would've been a rare case. But I think
it's no longer necessary on modern compilers. And, again at least
with GCC, you can put the block inside parens too, and it'll still
compile fine--without the need for the loop construct, and making it
completely safe to use in any context. But again, I'm not sure how
other compilers would react to that syntax. I frequently use that
syntax in a macro I have to ignore return values, albeit with C++:
// GCC 4.6 has made it very difficult to ignore return values from some
library
// functions... This monstrosity solves that while keeping the intent clear.
#define IGNORE_VAL(expr)\
({ typeof(expr) __ignval __attribute((unused)) = (expr); })
But AFAIK it should work fine in C as well--with gcc.
Regardless, I appear to have gotten the point across about
strncpy()/strlcpy()/strfcpy() -- and if we're cleaning this up, we
should probably move the macro to protos.h or similar and remove the
multiple/different definitions of it elsewhere.
--
Derek D. Martin http://www.pizzashack.org/ GPG Key ID: 0xDFBEAD02
-=-=-=-=-
This message is posted from an invalid address. Replying to it will result in
undeliverable mail due to spam prevention. Sorry for the inconvenience.
pgp4NzoGP9PIc.pgp
Description: PGP signature
