Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated references from C11->C23

...

The gets_s() function reads, at most, one less than the number of characters specified from the stream pointed to by stdin into an array.

The C Standard, Annex K 3.5.4.1 paragraph 4 [ISO/IEC 9899:20112024], states

No additional characters are read after a new-line character (which is discarded) or after end-of-file. The discarded new-line character does not count towards number of characters read. A null character is written immediately after the last character read into the array.

...

In this compliant solution, characters are no longer copied to buf once index == BUFFERSIZE - 1, leaving room to null-terminate the string. The loop continues to read characters until the end of the line, the end of the file, or an error is encountered. When chars_read > index truncated == true, the input string has been truncated.

Code Block
bgColor#ccccff
langc
#include <stdio.h>
 
enum { BUFFERSIZE = 32 };
 
void func(void) {
  char buf[BUFFERSIZE];
  int ch;
  size_t index = 0;
  size_t chars_readbool truncated = 0false;
 
  while ((ch = getchar()) != '\n' && ch != EOF) {
    if (index < sizeof(buf) - 1) {
      buf[index++] = (char)ch;
    } else {
     chars_read++ truncated = true;
    }
  }
  buf[index] = '\0';  /* Terminate string */
  if (ch == EOF) {
    /* Handle EOF or error */
  }
  if (chars_read > indextruncated) {
    /* Handle truncation */
  }
}

...

Code Block
bgColor#ccccff
langc
#include <stdio.h>
 
void func(const char *name) {
  char filename[128];
  sprintf(filename, "%.123s.txt", name);
}

Compliant Solution (snprintf())

A more general solution is to use the snprintf() functionYou can also use * to indicate that the precision should be provided as a variadic argument:

Code Block
bgColor#ccccff
langc
#include <stdio.h>
 
void func(const char *name) {
  char filename[128];
  snprintfsprintf(filename, "%.*s.txt", sizeof(filename), "%s.txt" - 5, name);
}

Risk Assessment

Compliant Solution (snprintf())

A more general solution is to use the snprintf() function, which also truncates name if it will not fit in the filename.

Code Block
bgColor#ccccff
langc
#include <stdio.h>
 
void func(const char *name) {
  char filename[128];
  int result = snprintf(filename, sizeof(filename), "%s.txt", name);
  if (result != strlen(filename) {
    /* truncation occurred */
  }
}

Risk Assessment

Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can exploit this Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can exploit this condition to execute arbitrary code with the permissions of the vulnerable process.

...

0145, 2840, 2841, 2842, 2843, 2845, 2846, 2847, 2848, 2930, 2931, 2932, 2933, 2935, 2936, 2937, 2938, 5006, 5038

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V

Supported

Astrée reports all buffer overflows resulting from copying data to a buffer that is not large enough to hold that data.

Axivion Bauhaus Suite
Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V
CertC-STR31

Detects calls to unsafe string function that may cause buffer overflow
Detects potential buffer overruns, including those caused by unsafe usage of fscanf()

CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.MEM.BO
LANG.MEM.TO
MISC.MEM.NTERM
BADFUNC.BO.*

Buffer overrun
Type overrun
No space for null terminator
A collection of warning classes that report uses of library functions prone to internal buffer overflows

Compass/ROSE



Can detect violations of the rule. However, it is unable to handle cases involving strcpy_s() or manual string copies such as the one in the first example

Coverity
Include Page
Coverity_V
Coverity_V

STRING_OVERFLOW

BUFFER_SIZE

OVERRUN

STRING_SIZE

Fully implemented

Fortify SCA

5.0



Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C2840,  C5009, C5038

C++0145, C++5009, C++5038

DF2840, DF2841, DF2842, DF2843, DF2845, DF2846, DF2847, DF2848, DF2930, DF2931, DF2932, DF2933, DF2935, DF2936, DF2937, DF2938


Helix QAC
Include Page
Helix QAC_VHelix QAC_V

Klocwork

Include Page
Klocwork_V
Klocwork_V

NNTS.MIGHT
NNTS.MUST

SV.STRBO.BOUND_COPY.OVERFLOW
SV.STRBO.BOUND_COPY.UNTERM
SV.STRBO.BOUND_SPRINTF
SV.STRBO.UNBOUND_COPY
SV.STRBO.UNBOUND_SPRINTFFMT_STR.BAD_SCAN_FORMAT
SV.UNBOUND_STRING_INPUT.FUNC


LDRA tool suite

Include Page
LDRA_V
LDRA_V

489 S, 109 D, 66 X, 70 X, 71 X

Partially implemented

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-STR31-a
CERT_C-STR31-b
CERT_C-STR31-c
CERT_C-STR31-d
CERT_C-STR31-e

Avoid accessing arrays out of bounds
Avoid overflow when writing to a buffer
Prevent buffer overflows from tainted data
Avoid buffer write overflow from tainted data
Avoid using unsafe string functions which may cause buffer overflows

PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

421, 498

Partially supported

Partially supported

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule STR31-C

Checks for:

  • Use of dangerous standard function
  • Missing null in string array
  • Buffer overflow from incorrect string format specifier
  • Destination buffer overflow in string manipulation
  • Insufficient destination buffer size

Rule partially covered.

Polyspace Bug Finder
Include Page
Polyspace Bug Finder_VPolyspace Bug Finder_V

CERT C: Rule STR31-C

Checks for:

  • Use of dangerous standard function
  • Missing null in string array
  • Buffer overflow from incorrect string format specifier
  • Destination buffer overflow in string manipulation
  • Tainted NULL or non-null-terminated string

Rule partially covered.

PRQA QA-C
Include Page
PRQA QA-C_vPRQA QA-C_v5009, 5038, 2840, 2841, 2842, 2843, 2845, 2846, 2847, 2848, 2930, 2931, 2932, 2933, 2935, 2936, 2937, 2938Partially implementedPRQA QA-C++
Include Page
cplusplus:PRQA QA-C++_Vcplusplus:PRQA QA-C++_V
PVS-Studio

Include Page
PVS-Studio_V
PVS-Studio_V

V518, V645, V727, V755

Splint

Include Page
Splint_V
Splint_V



TrustInSoft Analyzer

Include Page
TrustInSoft Analyzer_V
TrustInSoft Analyzer_V

mem_access

Exhaustively verified (see one compliant and one non-compliant example).

...

[Dowd 2006]Chapter 7, "Program Building Blocks" ("Loop Constructs," pp. 327–336)
[Drepper 2006]Section 2.1.1, "Respecting Memory Bounds"
[ISO/IEC 9899:20112024]K.3.5.4.1, "The gets_s Function"
[Lai 2006]
[NIST 2006]SAMATE Reference Dataset Test Case ID 000-000-088
[Seacord 2013b]Chapter 2, "Strings"
[xorl 2009]FreeBSD-SA-09:11: NTPd Remote Stack Based Buffer Overflows

[BC]

New Linux SUDO flaw lets local users gain root privileges

...