ok@quintus (11/16/88)
The getsafe()/fgetsafe() functions recently posted to comp.sources.misc contain two bugs: the "number of characters consumed" count is off by 1 in some cases, and it was possible for a hacker to break them just like the old ones, by providing more than 2**32 characters of input. Context diffs to be applied to getsafe.c: *** getsafe.old.c Fri Nov 14 01:34:43 1988 --- getsafe.c Tue Nov 15 23:24:39 1988 *************** *** 1,7 **** /* File : getsafe.c Author : Richard A. O'Keefe @ Quintus Computer Systems, Inc. ! Updated: 11 November 1988 ! Defines: getsafe() and fgetsafe() -- safe replacements for gets() This file is not covered by a copyright. Do what you like with it. --- 1,6 ---- /* File : getsafe.c Author : Richard A. O'Keefe @ Quintus Computer Systems, Inc. ! Updated: 15 November 1988 Defines: getsafe() and fgetsafe() -- safe replacements for gets() This file is not covered by a copyright. Do what you like with it. *************** *** 30,35 **** --- 29,37 ---- n = getsafe(buffer, sizeof buffer); if (n > sizeof buffer) { the line was truncated } + If the line was not truncated, and if the input contained no NUL + characters, getsafe()'s return value will be strlen(buffer)+1. + If a new-line character is not encountered, characters will have been read until the end of the stream was reached, and the return value is 0 to indicate end of stream. This means that a last "line" which is *************** *** 41,46 **** --- 43,51 ---- can be converted to while (getsafe(buffer, sizeof buffer)) { process line } + BEWARE: if the input line is _really_ long, C's pathetic arithmetic + would make n wrap around. fgetsafe() checks for that, and makes n + stick at the most positive integer. #endif 0 int fgetsafe(buffer, length, stream) *************** *** 51,63 **** register int c; register int n; ! for (n = 0;;) { ! c = getc(stream); ! if (c == EOF ) { *buffer = '\0'; return 0; } ! if (c == '\n') { *buffer = '\0'; return n; } ! n++; ! if (n < length) *buffer++ = c; } } --- 56,71 ---- register int c; register int n; ! for (n = 0; ; *buffer++ = c) { ! if ((c = getc(stream)) == EOF) break; ! if (++n >= length || c == '\n') break; } + *buffer++ = '\0'; + while (c != '\n') { + if ((c = getc(stream)) == EOF) return 0; + if (++n < 0) --n; + } + return n; } --