Re: strcpy versus strncpy

From: Andy Church (achurchat_private)
Date: Mon Mar 02 1998 - 19:54:02 PST

  • Next message: Cain: "updatedb stuff"

    Morten Welinder <terraat_private> writes:
    
    >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.
    
         I agree with you in part and disagree with you in part.  I agree that
    using strcpy should not automatically be considered a bug, and in fact, I
    have tried to make that argument myself a few times, with varying levels of
    success.  However, your claims fail to convince me that the very same
    argument does not apply to strncpy.  You claim, in summary (to avoid a long
    quote):
    
    1. Different size buffers can result in different strings when dealing with
       a long file name.
    
    2. Such different strings will have different meanings with respect to the
       filesystem.
    
    3. Assumptions should not be made about the size of an object.
    
         The first two are arguably true; it is trivial to create an example in
    which a long filename gets truncated so that it refers to a different file.
    However, filename buffers are hardly the only place where strncpy/snprintf
    are used; for example, in my IRC services program, only a couple out of
    dozens of such calls are used with filename buffers (most of the rest deal
    with message and identifier length).
    
         Which brings me to your third point.  I can agree with it as written
    (both here and in the original message); however, I find it a rather weak
    claim.  Assumptions are generally bad, yes; however, in many cases, the
    issue is not making an assumption, but setting a limit.  And I _do_ believe
    that setting limits is a good thing.  Suppose, for example, that you could
    create filenames of any length in a filesystem.  The following script:
    
    ----------------
    #!/bin/sh
    a="`yes | dd bs=1024 count=1024`"   # Create a 1048576-byte variable
    i=0
    while touch /tmp/$a$i ; do
            i=`expr $i + 1`
    done
    ----------------
    
    would happily fill up whatever filesystem /tmp happened to be on.  Disk
    quotas wouldn't block it--/tmp is owned by root, and filenames are stored
    in the directory file, not separately (at least in the Linux ext2
    filesystem; I don't know about others).  If your file quota was too low to
    prevent filling up the filesystem, you could just lengthen the filename.
    Or suppose your SMTP server happily accepted strings of any length on its
    input, terminated by <CR><LF>.  Here's a nifty little memory eater:
    
    ----------------
    #!/bin/sh
    a="dd if=/dev/zero bs=1024 count=1024`"   # 1MB of nulls
    while true ; do
            echo $a | nc victim 25 &
            sleep 10   # Give the data a chance to get out
    done
    ----------------
    
    (use netcat instead of telnet to avoid telnet's problem with quitting on
    EOF).  Granted, this attack would take a huge amount of bandwidth, but you
    get the idea.
    
         Moreover, truncation is not, by itself, a bug; it's simply the way a
    particular program works.  The fact that a program does not do what may
    seem intuitive does not mean the program is buggy; for example, I seriously
    doubt many people would consider gcc to be buggy solely on the basis that
    it fails to compile the following one-line program:
    
    ----------------
    int main() { puts(NameOfThisProgram); return 0; }
    ----------------
    
    even though the intention is obvious.  (Yes, this is a farfetched example,
    but the point is there.)  There may of course be other bugs triggered by
    truncation, such as symlink-following, but those are bugs on their own.
    
         So, where you have limits, strncpy/snprintf are generally to be
    preferred.  Where you allocate string buffers dynamically, strcpy/sprintf
    will do fine.  Neither is a bug in and of itself.  And, of course, neither
    is a panacea; it's still necessary to write code carefully.
    
      --Andy Church                  | If Bell Atlantic really is the heart
        achurchat_private       | of communication, then it desperately
        www.dragonfire.net/~achurch/ | needs a quadruple bypass.
    



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