Email List: Xaustin-group-lX
[All Lists]

[1003.1(2008)/Issue 7 0000182]: Unsafe use of LINE_MAX in fgets() exampl

To: austin-group-l@xxxxxxxxxxxxx
Subject: [1003.1(2008)/Issue 7 0000182]: Unsafe use of LINE_MAX in fgets() example
From: Austin Group Bug Tracker <noreply@xxxxxxxxxxxxx>
Date: Thu, 12 Nov 2009 19:24:16 +0000
Keywords: [1003.1(2008)/Issue 7] System Interfaces
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             => ---             
======================================================================

<Prev in Thread] Current Thread [Next in Thread>