Re: strcpy versus strncpy

From: Daniel Reed (djrat_private)
Date: Mon Mar 02 1998 - 18:46:36 PST

  • Next message: Bryan Andregg: "Re: overwrite any file with updatedb"

    On Tue, 3 Mar 1998, Morten Welinder wrote:
    ) A recent article on BugTraq suggested that using strcpy should
    ) almost always be considered a bug.  That's not right.  It is,
    ) in fact, the wrong way around: strncpy is almost always a bug.
    )
    ) True, strncpy will avoid buffer overruns, but that only proven
    ) that strncpy is better than incorrect use of strcpy.  The problem
    ) is that such use of strncpy can introduce problems of its own:
     [...]
    ) With dynamic allocating available, there really is no execuse for
    ) using strncpy, with the possible exception where memory attacks
    ) might be a larger problem, but that should not be the case with
    ) argv/environ based strings.
    Recently on the vcppat_private mailing list someone asked about
    creating their own function similar to printf(), to which I gave the
    minimal example:
    
    #include <stdarg.h>             // for the va_* stuff
    #include <stdio.h>              // for fputs() and stdout
    #include <string.h>             // for bzero()
    
    #define BUFSIZE 1024            // how big is our internal buffer
    #define BUFLEN  (BUFSIZE-1)     // how many bytes of our internal buffer
                                    // can we use (BUFSIZE - 1 for the NULL
                                    // terminator)
    
    char    *MySprintf(char *format, ...) {
            static char     buf[BUFSIZE];
                                    // this is our buffer to store the
                                    // formatted string into
            va_list msg;            // this is how we access the ...
    
            bzero(buf, BUFSIZE);    // clear out our buffer
            va_start(msg, format);  // then attach the ... with the format
            vsnprintf(buf, BUFLEN, format, msg);
                                    // then stick the formatted string into
                                    // buf (but only use BUFLEN bytes of buf,
                                    // to avoid a buffer overflow)
            va_end(msg);            // clean up
            return(buf);            // send back a pointer to our static buffer
    }
    
    
    I made a note that this wasn't multi-thread safe, as calling MySprintf()
    again would overwrite the static buffer for MySprintf().
    
    If I had made this use dynamic memory, instead of a static internal
    buffer, the user would then have to deal with free()'ing a section of
    memory they did not allocate--my function did! If nothing else, that's
    poor coding style (in my opinion), and at worse, leads to hard-to-trace
    memory leaks.
    
    So, discounting dynamic memory allocation, could you fault me for shunning
    vsprintf() and instead using vsnprintf()?
    
     ...
    
    int     main(int argc, char **args) {
            printf("Shell login wrapper loading.\n");
            printf("\n");
            if (getuid() == 0)
                    execl(MySprintf("%s.root", getenv("SHELL")), args[0], NULL);
            /* set user limits and stuff */
            execl(MySprintf("%s.user", getenv("SHELL")), args[0], NULL);
    }
    
    as a trivial example. As a not so trivial example, think of something like
    sendmail, which runs forever, and uses a lot of automatic buffers. Running
    as root, having a static buffer and using strcpy/sprintf/vsprintf, buffer
    overflows are possibly exploitable. As any user, having a dynamic buffer
    and using anything, memory starvation (or CPU starvation, in fact;
    malloc() is an expensive call) is possible. Under any user, using a static
    buffer with strncpy/snprintf/vsnprintf, buffer overflows are significantly
    reduced (if not eliminated), resource starvation is significantly reduced
    (if not eliminated), and at worse an incoming, legitimate message will be
    bounced because it overflows a buffer. I believe in [one of] the SMTP
    RFC[s] a maximum line length is defined for commands.
    
    --
    Daniel Reed <nat_private> (3CE060DD)
    System administrator of narnia.n.ml.org (narnia.mhv.net [199.0.0.118])
    I'm so glad to see you! I've run out of people to torment...
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:43:36 PDT