diff options
author | Chad Loder <cloder@cvs.openbsd.org> | 2006-10-14 23:57:40 +0000 |
---|---|---|
committer | Chad Loder <cloder@cvs.openbsd.org> | 2006-10-14 23:57:40 +0000 |
commit | dba8c558535c38f881f7b7036ca133d4000f1970 (patch) | |
tree | 05314895fe837c190d785f4c28fd7f9a954ba932 | |
parent | 8ad6a4c4e4afe7be8dc3c334a9b9abac22607f0d (diff) |
Add a CAVEAT section that describes how to properly trim a newline from
a string, being careful to deal with 0-length strings. Help and input
from jmc, ok deraadt
-rw-r--r-- | lib/libc/stdio/fgets.3 | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/lib/libc/stdio/fgets.3 b/lib/libc/stdio/fgets.3 index 62f6fb8e7b4..65b72fe0b7e 100644 --- a/lib/libc/stdio/fgets.3 +++ b/lib/libc/stdio/fgets.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: fgets.3,v 1.22 2006/10/14 18:50:32 cloder Exp $ +.\" $OpenBSD: fgets.3,v 1.23 2006/10/14 23:57:39 cloder Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -147,17 +147,17 @@ conform to .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; +.Bd -literal -offset indent +char buf[1024], *p; - while (fgets(buf, sizeof(buf), fp) != NULL) { - if ((p = strchr(buf, '\en')) == NULL) { - fprintf(stderr, "input line too long.\en"); - exit(1); - } - *p = '\e0'; - printf("%s\en", buf); +while (fgets(buf, sizeof(buf), fp) != NULL) { + if ((p = strchr(buf, '\en')) == NULL) { + fprintf(stderr, "input line too long.\en"); + exit(1); } + *p = '\e0'; + printf("%s\en", buf); +} .Ed .Pp While the error would be true if a line > 1023 characters were read, it would @@ -189,6 +189,37 @@ which may indeed include a newline. Consider using .Xr fgetln 3 instead when dealing with untrusted input. +.Pp +It is erroneous to assume that +.Fn fgets +never returns an empty string when successful. +If a line starts with the NUL character, fgets will store the NUL and +continue reading until it encounters a newline or end-of-file. +This will result in an empty string being returned. +The following bit of code illustrates a case where the programmer assumes +the string cannot be zero length. +.Bd -literal -offset indent +char buf[1024]; + +if (fgets(buf, sizeof(buf), fp) != NULL) { + /* WRONG */ + if (buf[strlen(buf) - 1] == '\en') + buf[strlen(buf) - 1] = '\e0'; +} +.Ed +.Pp +If +.Fn strlen +returns 0, the index into the buffer becomes \-1. +The correct way to trim a newline is shown below. +.Bd -literal -offset indent +char buf[1024]; + +if (fgets(buf, sizeof(buf), fp) != NULL) { + if (buf[0] != '\e0' && buf[strlen(buf) - 1] == '\en') + buf[strlen(buf) - 1] = '\e0'; +} +.Ed .Sh BUGS Since it is usually impossible to ensure that the next input line is less than some arbitrary length, and because overflowing the |