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.

Attachment: pgp4NzoGP9PIc.pgp
Description: PGP signature

Reply via email to