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