Main Content

CERT C: Rec. PRE09-C

Do not replace secure functions with deprecated or obsolescent functions

Description

Rule Definition

Do not replace secure functions with deprecated or obsolescent functions.1

Polyspace Implementation

The rule checker checks for these issues:

  • Use of dangerous standard function.

  • Insufficient destination buffer size.

Examples

expand all

Issue

The Use of dangerous standard function check highlights uses of functions that are inherently dangerous or potentially dangerous given certain circumstances. The following table lists possibly dangerous functions, the risks of using each function, and what function to use instead.

Dangerous FunctionRisk LevelSafer Function
getsInherently dangerous — You cannot control the length of input from the console.fgets
cinInherently dangerous — You cannot control the length of input from the console.Avoid or prefaces calls to cin with cin.width.
strcpyPossibly dangerous — If the source length is greater than the destination, buffer overflow can occur.strncpy
stpcpyPossibly dangerous — If the source length is greater than the destination, buffer overflow can occur.stpncpy
lstrcpy or StrCpyPossibly dangerous — If the source length is greater than the destination, buffer overflow can occur.StringCbCopy, StringCchCopy, strncpy, strcpy_s, or strlcpy
strcatPossibly dangerous — If the concatenated result is greater than the destination, buffer overflow can occur.strncat, strlcat, or strcat_s
lstrcat or StrCatPossibly dangerous — If the concatenated result is greater than the destination, buffer overflow can occur.StringCbCat, StringCchCat, strncay, strcat_s, or strlcat
wcpcpyPossibly dangerous — If the source length is greater than the destination, buffer overflow can occur.wcpncpy
wcscatPossibly dangerous — If the concatenated result is greater than the destination, buffer overflow can occur.wcsncat, wcslcat, or wcncat_s
wcscpyPossibly dangerous — If the source length is greater than the destination, buffer overflow can occur.wcsncpy
sprintfPossibly dangerous — If the output length depends on unknown lengths or values, buffer overflow can occur.snprintf
vsprintfPossibly dangerous — If the output length depends on unknown lengths or values, buffer overflow can occur.vsnprintf
Risk

These functions can cause buffer overflow, which attackers can use to infiltrate your program.

Fix

The fix depends on the root cause of the defect. Often the result details show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show the event history, you can trace back using right-click options in the source code and see previous related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface.

See examples of fixes below.

If you do not want to fix the issue, add comments to your result or code to avoid another review. See:

Example - Using sprintf
#include <stdio.h>
#include <string.h>
#include <iostream>

#define BUFF_SIZE 128


int dangerous_func(char *str)
{
    char dst[BUFF_SIZE];
    int r = 0;

    if (sprintf(dst, "%s", str) == 1) //Noncompliant
    {
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}

This example function uses sprintf to copy the string str to dst. However, if str is larger than the buffer, sprintf can cause buffer overflow.

Correction — Use snprintf with Buffer Size

One possible correction is to use snprintf instead and specify a buffer size.

#include <stdio.h>
#include <string.h>
#include <iostream>

#define BUFF_SIZE 128


int dangerous_func(char *str)
{
    char dst[BUFF_SIZE];
    int r = 0;

    if (snprintf(dst, sizeof(dst), "%s", str) == 1)
    {
        r += 1;
        dst[BUFF_SIZE-1] = '\0';
    }
    
    return r;
}
Issue

Insufficient destination buffer size occurs when the destination buffer in a strcpy operation cannot accommodate the source buffer and a null terminator. This issue is reported if the size of the source buffer is unknown. Consider this code:

int main (int argc, char *argv[])
{
  const char *const input = ((argc && argv[0]) ? argv[0] : "");
  char str[100];
  strcpy(input, str); // Noncompliant
}
In this case, the size of the source buffer input is unknown. The size of the destination buffer str might be smaller than the value (strlen(input)+1). Polyspace® reports a violation on the strcpy operation.

Risk

Using a destination buffer of insufficient size might allow an attacker to cause a buffer overflow. In the preceding code example, if argv[0] contains 100 or more characters, the strcpy operation results in a buffer overflow.

Fix

Before calling the function strcpy(), allocate sufficient memory dynamically. For instance, use the function strlen() to determine the size of the source buffer and then allocate the destination buffer so that its size is greater than the value strlen(source) + 1.

Example — Destination Buffer Too Small

In this example, the size of the source buffer is unknown, while the size of the destination buffer is fixed at 128. The size of the destination buffer might not be sufficient to accommodate the characters from the source buffer and terminate the buffer with a null. Polyspace reports a violation of the rule.

#include <string.h>
  
int main(int argc, char *argv[]) {
  const char *const source = (argc && argv[0]) ? argv[0] : "";
  char destination[128];
  strcpy(source, destination);//Noncompliant
  
  return 0;
}
Correction — Allocate Sufficient Memory for Destination Buffer

This violation is resolved by allocating sufficient memory for the destination buffer. For instance, use the function strlen() to calculate the size of the source buffer and allocate sufficient memory for the destination buffer so that it can accommodate all characters from the source buffer and the null terminator ('\0' ).

#include <string.h>
  
int main(int argc, char *argv[]) {
  const char *const source = (argc && argv[0]) ? argv[0] : "";
  char* destination = (char *)malloc(strlen(source)+ 1);
  if(destination!=NULL){
      strcpy(source, destination);//Compliant
  }else{
      /*Handle Error*/
  }
  //...
  free(destination);
  return 0;
}

Check Information

Group: Rec. 01. Preprocessor (PRE)

Version History

Introduced in R2019a

expand all


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.