The following issue has been SUBMITTED.
======================================================================
http://austingroupbugs.net/view.php?id=182
======================================================================
Reported By: Don Cragun
Assigned To: ajosey
======================================================================
Project: 1003.1(2008)/Issue 7
Issue ID: 182
Category: System Interfaces
Type: Error
Severity: Comment
Priority: normal
Status: Under Review
Name: Don Cragun
Organization: Self
User Reference: fgets() LINE_MAX
Section: fgets() EXAMPLES
Page Number: 852
Line Number: 28298-28308
Interp Status: ---
Final Accepted Text:
======================================================================
Date Submitted: 2009-11-12 19:23 UTC
Last Modified: 2009-11-12 19:23 UTC
======================================================================
Summary: Unsafe use of LINE_MAX in fgets() example
Description:
Several issues have been discussed on the Austin Group's e-mail
list related to LINE_MAX. The discussion started with a discussion
about the use of LINE_MAX in the example on the description of the
fgets() function, and branched into a discussion about the differences
between the definition of LINE_MAX in <limits.h> and the legal
return values for a call to sysconf(_SC_LINE_MAX); This bug report
intends to resolve all of the issues raised except for the use of
LINE_MAX in an example on the description of the strtok() function
which has already been addressed by the resolution of bug #177 (See
http://austingroupbugs.net/view.php?id=177.)
The Utility Limits rationale (subclause C.1.3 on P3639, L123638-123646)
already warns application writers that it is not a good idea to
"blindly" allocate an array of size [LINE_MAX] and assume that it
will be large enough to hold a full input line. Further guidance
later in that section (P3640, L123685-123701) warns about creating
lines longer than LINE_MAX and needing to be careful if those lines
will later become input to a utility that is specified to process
text files.
I believe that it is safe to assume that applications using fgets()
already assume that any stream being read with fgets() is connected
to a text file. If the application does not have reason to believe
that the input is from a text file, it should be using functions
like read() or fread() rather than functions like fgets() and
getline().
Desired Action:
<pre>
In XBD, <limits.h>, Minimum Values section, P274, L9019-9020 change:
A conforming implementation shall provide values at least this
large.
to:
For each of these limits, a conforming implementation shall
provide a value at least this large or shall have no limit.
In XSH, fgets(), EXAMPLES section, P852, L28298-28308 change:
The following example uses fgets() to read each line of
input. {LINE_MAX}, which defines the maximum size of the
input line, is defined in the <limits.h> header.
#include <stdio.h>
...
char line[LINE_MAX];
...
while (fgets(line, LINE_MAX, fp) != NULL) {
...
}
...
to:
The following example uses fgets() to read lines of input.
It assumes that the file it is reading is a text file and
that lines in this text file are no longer than 16384 (or
[LINE_MAX] if it is less than 16384 on the implementation
where it is running) bytes long. (Note that the standard
utilities have no line length limit if sysconf(_SC_LINE_MAX)
returns -1 without setting errno. This example assumes that
sysconf(_SC_LINE_MAX) will not fail.)
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#define MYLIMIT 16384
char *line;
int line_max;
if (LINE_MAX >= MYLIMIT) {
// Use maximum line size of MYLIMIT. If LINE_MAX is
// bigger than our limit, sysconf() can't report a
// smaller limit.
line_max = MYLIMIT;
} else {
long limit = sysconf(_SC_LINE_MAX);
line_max = (limit < 0 || limit > MYLIMIT) ? MYLIMIT : (int)limit;
}
// line_max + 1 leaves room for the nul byte added by fgets().
line = malloc(line_max + 1);
if (line == NULL) {
// out of space
...
return error;
}
while (fgets(line, line_max + 1, fp) != NULL) {
// Verify that a full line has been read...
// If not report an error or prepare to treat the
// next time through the loop as a read of a
// continuation of the current line.
...
// Process line...
...
}
free(line);
...
</pre>
======================================================================
Issue History
Date Modified Username Field Change
======================================================================
2009-11-12 19:23 Don Cragun New Issue
2009-11-12 19:23 Don Cragun Status New => Under Review
2009-11-12 19:23 Don Cragun Assigned To => ajosey
2009-11-12 19:23 Don Cragun Name => Don Cragun
2009-11-12 19:23 Don Cragun Organization => Self
2009-11-12 19:23 Don Cragun User Reference => fgets() LINE_MAX
2009-11-12 19:23 Don Cragun Section => fgets() EXAMPLES
2009-11-12 19:23 Don Cragun Page Number => 852
2009-11-12 19:23 Don Cragun Line Number => 28298-28308
2009-11-12 19:23 Don Cragun Interp Status => ---
======================================================================
|