> On Thu, 15 Jul 1999, Mike Smith wrote:
> 
> > Ugh.  Take the first example in the paper; it rewrites as
> > 
> >     len = asprintf(&path, "%s/.foorc");
> > 
> > as opposed to
> > 
> >     strlcat(path, homedir, sizeof(path));
> >     strlcat(path, "/", sizeof(path));
> >     strlcat(path, ".foord", sizeof(path));
> >     len = strlen(path);
> > 
> > Yes, they're a better str*cat/cpy, but they're not the solution that 
> > they claim to be.
> 
> I don't think that anyone has intended them to be anything other than a
> better replacement for strcpy/strcat than strncpy/strncat (which they
> certainly are).  Sure, you could go around telling people "use snprintf
> instead" or "use asprintf instead", but is that the issue at hand?

In context, yes it is.

The paper talks about dealing with the construction of composite 
strings into static buffers, and points out that there's a real problem 
when you hit the edge of the buffer (overflow, truncation, etc.)

But they don't address the core of the problem, which is the use of a 
static buffer in the first place.  This and other habitual programming 
style items are what's at the real core of the "C is an insecure 
language" argument; people are so used to these idiomatic programming 
techniques they refuse to look for better solutions to the larger 
problem.

Going back to the example they gave, let's put it in context.  You 
probably have something like this:


{
        struct passwd *pw;
        char    buf[MAXPATHLEN];
        FILE    *fp;
        
        pw = getpwuid(getuid());
        strlcpy(buf, pw->dir, sizeof(buf));
        strlcat(buf, "/.appname/", sizeof(buf));
        strlcat(buf, conffilename, sizeof(buf));
        if (strlen(buf) >= sizeof(buf))
                return(error);
        fp = fopen(buf, "r");
        ...

That works, as long as MAXPATHLEN is actually long enough.  In this 
particular case it will be (because fopen will fail otherwise), but 
there's no guarantee that you're going to know in advance.

OTOH, here it is with asprintf:

{
        struct passwd *pw;
        char    *buf;
        FILE    *fp;
        
        pw = getpwuid(getuid());
        if (asprintf(&buf, "%s/.appname/%s", pw->dir, conffilename) == -1)
                return(error);
        fp = fopen(buf, "r");
        free(buf);
        ...

The latter has a few really clear advantages:

 - you can see what the string is meant to look like.
 - it doesn't matter how long any of the components are.
 - the constructed value is on the heap, so you can return it (just 
   imagine how much nicer ctime() would be if it did this).

-- 
\\  The mind's the standard       \\  Mike Smith
\\  of the man.                   \\  [EMAIL PROTECTED]
\\    -- Joseph Merrick           \\  [EMAIL PROTECTED]




To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to