From owner-freebsd-questions Fri Mar 7 19:47:58 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id TAA14556 for questions-outgoing; Fri, 7 Mar 1997 19:47:58 -0800 (PST) Received: from who.cdrom.com (who.cdrom.com [204.216.27.3]) by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id TAA14539 for ; Fri, 7 Mar 1997 19:47:50 -0800 (PST) Received: from murkwood.gaffaneys.com (dialup13.gaffaneys.com [134.129.252.32]) by who.cdrom.com (8.8.5/8.6.11) with ESMTP id SAA02332 for ; Fri, 7 Mar 1997 18:10:21 -0800 (PST) Received: (from zach@localhost) by murkwood.gaffaneys.com (8.8.5/8.8.5) id UAA29285; Fri, 7 Mar 1997 20:10:02 -0600 (CST) To: "Jeffrey M. Metcalf" Cc: questions@freebsd.org, metcalf@snet.net Subject: Re: Re[2]: What does gets() unsafe question mean? References: <9702078577.AA857755172@ccgate0.bms.com> From: Zach Heilig Date: 07 Mar 1997 20:10:00 -0600 In-Reply-To: "Jeffrey M. Metcalf"'s message of Fri, 07 Mar 1997 09:03:54 -0500 (EST) Message-ID: <87zpwf5e2v.fsf@murkwood.gaffaneys.com> Lines: 94 X-Mailer: Gnus v5.4.15/XEmacs 19.14 Sender: owner-questions@freebsd.org X-Loop: FreeBSD.org Precedence: bulk "Jeffrey M. Metcalf" writes: > Thank You for the reply Zach, > I just wrote the following on a sun4 Change the program to this, and you'll see what I mean. For some reason, FreeBSD starts beeping after 1024 characters. It takes 9 characters to make it core-dump on FreeBSD. You only have to type 1 character (and enter) to see the effects. #include #define PRINT(x) printf( #x " = %d\n", (x)) main() { int before = 8; /* number doesn't matter, I tried to hit an ASCII * value you are unlikely to enter on a keyboard. */ char buf[1]; int after = 8; PRINT(before); PRINT(after); puts("Enter lots of text and press enter:"); gets(buf); puts("\n"); PRINT(before); PRINT(after); puts(buf); before=0; after=0; puts(buf); } That should show the problem up for sure. It does for FreeBSD anyway... > Entering a huge line of text results in the _exact_ same huge line > of text on stdout. Hardly surprising.. You obviously did not enter enough text to overwrite important parts of the stack. The program modified as above should show the problem better. (SunOS might have different data and return stacks?). > Why should this be if buf was only declared to be char[1]? Is it > because gets is allowing me to put characters into memory > sequentially and then when buf (pointer to the first character of > array, buf[0]) is returned via puts, I get everything until the > first newline? Or does SunOS have its own implementation of > gets()/puts()? Incidentally, I don't get the warning message from > SunOS. See, the problem is gets() has no clue how big the chunk of memory is that you passed to it. It will happily write characters until either the program crashes or it reads a newline. > You mentioned gets() creates problems and security holes with > setuid programs. Given the result in the above paragraph from > SunOS, is it reasonable to assume that a non setuid program that > uses gets() on SunOS is reasonably safe if the program is well > written? Or is there much more involved here? Since you the program writer won't have control over the input, it is impossible to create a "well-written program" using gets(). Even toy programs that write to a temporary file, and use gets() to read it back in have a race condition (some other program can change the file before we read it back). You may be able to get away with using gets() in a throwaway program, but definately do not use it for anything serious. > Lastly, is the fgets() function call the much better (and safer) > choice to get a line from stream? Since it reads 'at most n > chars' from stream, I presume it is safer due to more controllable > boundary conditions. Am I correct? Exactly, use fgets() and hack off the trailing '\n' if you don't need/want it. Just be careful there too, since there might not be a trailing '\n'. You might want to use something similar to: char input[64], *nlptr; while (fgets(input, sizeof input, stdin)) { if ((nlptr = strchr(input, '\n'))) *nlptr = 0; /* do more stuff */ } -- Zach Heilig (zach@blizzard.gaffaneys.com) | ALL unsolicited commercial email Support bacteria -- it's the only | is unwelcome. I avoid dealing form of culture some people have! | with companies that email ads.