diff options
-rw-r--r-- | lib/libc/stdio/fgetln.3 | 35 | ||||
-rw-r--r-- | lib/libc/stdio/fgets.3 | 46 |
2 files changed, 77 insertions, 4 deletions
diff --git a/lib/libc/stdio/fgetln.3 b/lib/libc/stdio/fgetln.3 index e859ae87882..c1298d11617 100644 --- a/lib/libc/stdio/fgetln.3 +++ b/lib/libc/stdio/fgetln.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: fgetln.3,v 1.4 1999/07/21 12:21:29 aaron Exp $ +.\" $OpenBSD: fgetln.3,v 1.5 1999/09/15 21:26:58 aaron Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -56,8 +56,7 @@ The length of the line, including the final newline, is stored in the memory location to which .Fa len points. -(Note, however, that if the line is the last -in a file that does not end in a newline, +(Note, however, that if the last line in the stream does not end in a newline, the returned text will not contain a newline.) .Sh RETURN VALUES Upon successful completion a pointer is returned; @@ -112,6 +111,36 @@ for any of the errors specified for the routines .Xr stat 2 , or .Xr realloc 3 . +.Sh CAVEATS +Since the returned buffer is not a C string (it is not null terminated), a +common practice is to replace the newline character with +.Sq \e0 . +However, if the last line in a file does not contain a newline, +the returned text won't contain a newline either. +The following code demonstrates how to deal with this problem by allocating a +temporary buffer: +.Bd -literal + char *buf, *lbuf; + size_t len; + + lbuf = NULL; + while ((buf = fgetln(fp, &len))) { + if (buf[len - 1] == '\en') + buf[len - 1] = '\e0'; + else { + lbuf = (char *)malloc(len + 1); + memcpy(lbuf, buf, len); + lbuf[len] = '\e0'; + buf = lbuf; + } + printf("%s\en", buf); + + if (lbuf != NULL) { + free(lbuf); + lbuf = NULL; + } + } +.Ed .Sh SEE ALSO .Xr ferror 3 , .Xr fgets 3 , diff --git a/lib/libc/stdio/fgets.3 b/lib/libc/stdio/fgets.3 index 5a64ff70208..ef0dbfd5692 100644 --- a/lib/libc/stdio/fgets.3 +++ b/lib/libc/stdio/fgets.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: fgets.3,v 1.6 1999/07/09 13:35:23 aaron Exp $ +.\" $OpenBSD: fgets.3,v 1.7 1999/09/15 21:26:58 aaron Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -124,6 +124,50 @@ may also fail and set .Va errno for any of the errors specified for the routine .Xr getchar 3 . +.Sh CAVEATS +The following bit of code illustrates a case where the programmer assumes a +string is too long if it does not contain a newline: +.Bd -literal + char buf[1024], *p; + + while (fgets(buf, sizeof(buf), fp)) { + if (!(p = strchr(buf, '\en')) { + fprintf(stderr, "input line too long.\n"); + exit(1); + } + *p = '\e0'; + printf("%s\en", p); + } +.Ed +.Pp +While the error would be true if a line > 1023 characters were read, it would +be false in two other cases: +.Bl -enum -offset indent +.It +If the last line in a file does not contain a newline, the string returned by +.Fn fgets +will not contain a newline either. Thus +.Fn strchr +will return +.Dv NULL +and the program will terminate, even if the line was valid. +.It +All C string functions, including +.Fn strchr , +correctly assume the end of the string is represented by a null +.Pq Sq \e0 +character. +If the first character of a line returned by +.Fn fgets +were null, +.Fn strchr +would immediately return without considering the rest of the returned text +which may indeed include a newline. +.El +.Pp +Consider using +.Xr fgetln 3 +instead when dealing with untrusted input. .Sh SEE ALSO .Xr feof 3 , .Xr ferror 3 , |