TICS Coding Standard Viewer 
TIOBE Software Quality Framework
Print-friendly version
©TIOBE Software www.tiobe.com
 
C++ Coding Standard
Search

Rule:  FIO37-CChecked automatically with code checker

Synopsis:Do not assume that fgets() or fgetws() returns a nonempty string when successful
Language:C++
Severity Level:1
Category:Security


Description:

Errors can occur when incorrect assumptions are made about the type of data being read. These assumptions may be violated, for example, when binary data has been read from a file instead of text from a user's terminal or the output of a process is piped to stdin. (See FIO14-C. Understand the difference between text mode and binary mode with file streams.) On some systems, it may also be possible to input a null byte (as well as other binary codes) from the keyboard.

Subclause 7.21.7.2 of the C Standard [ISO/IEC 9899:2011] says,

The fgets function returns s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned.

The wide-character function  fgetws() has the same behavior. Therefore, if fgets()  or fgetws()  returns a non-null pointer, it is safe to assume that the array contains data. However, it is erroneous to assume that the array contains a nonempty string because the data may contain null characters.

Noncompliant Code Example

This noncompliant code example attempts to remove the trailing newline ( \n ) from an input line. The fgets() function is typically used to read a newline-terminated line of input from a stream. It takes a size parameter for the destination buffer and copies, at most, size - 1 characters from a stream to a character array.

#include <stdio.h>
#include <string.h>
   
enum { BUFFER_SIZE = 1024 };
 
void func( void ) {
   char buf[BUFFER_SIZE];
 
   if ( fgets (buf, sizeof (buf), stdin) == NULL) {
     /* Handle error */
   }
   buf[ strlen (buf) - 1] = '\0' ;
}

The strlen() function computes the length of a string by determining the number of characters that precede the terminating null character. A problem occurs if the first character read from the input by fgets() happens to be a null character. This may occur, for example, if a binary data file is read by the fgets() call [Lai 2006]. If the first character in buf is a null character, strlen(buf) returns 0, the expression strlen(buf) - 1 wraps around to a large positive value, and a write-outside-array-bounds error occurs.

Compliant Solution

This compliant solution uses strchr() to replace the newline character in the string if it exists:

#include <stdio.h>
#include <string.h>
   
enum { BUFFER_SIZE = 1024 };
 
void func( void ) {
   char buf[BUFFER_SIZE];
   char *p;
 
   if ( fgets (buf, sizeof (buf), stdin)) {
     p = strchr (buf, '\n' );
     if (p) {
       *p = '\0' ;
     }
   } else {
     /* Handle error */
   }
}