Versions Compared

Key

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

In C99, undefined behavior can result when If control reaches the end closing curly brace (}) of a non-void function without evaluating a return statement, and using the return value of the function call is used. This is almost always a programming error, and can lead to unexpected behavior.

This rule is related to MSC01-C. Strive for logical completeness.

undefined behavior. (See undefined behavior 86.)

Noncompliant Code Example

In this noncompliant code example, control reaches the end of the checkpass() function when the two strings passed to strcmp() are not equal. This leads to , resulting in undefined behavior, and various . Many compilers will generate code equivalent to for the checkpass() function, returning various values when along the execution path where no return checkpass() statement is reacheddefined.

Code Block
bgColor#ffcccc
lang#FFCCCCc
#include <string.h>
#include <stdio.h>
 
int checkpass(const char *password) {
  if (strcmp(password, "pass") == 0) {
    return 1;
  }
}
/* ... */


void func(const char *userinput) {
  if (checkpass(userinput)) {
    printf("Success!\n");
  }
}

This error is frequently diagnosed by compilers. (see See MSC00-C. Compile cleanly at high warning levels.)

Compliant Solution

This compliant solution ensures that the checkpass() function always returns a value:

Code Block
bgColor#ccccff
langc
#include <string.

...

h>
#include <stdio.h>
 
int checkpass(const char *password) {
  if (strcmp(password, "pass") == 0) {
    return 1;
  }
  return 0;
}

void func(const char *userinput) {
  if (checkpass(userinput)) {
    printf("Success!\n");
  }
}

Noncompliant Code Example

In this noncompliant code example, control reaches the end of the getlen() function when input does not contain the integer delim. Because the potentially undefined return value of getlen() is later used as an index into an array, a buffer overflow may occur.

Code Block
bgColor#ffcccc
langc
#include <stddef.h>
 
size_t getlen(const int *input, size_t maxlen, int delim) {
  for (size_t i = 0; i < maxlen; ++i) {
    if (input[i] == delim) {
      return i;
    }
  }
}
 
void func(int userdata) {
  size_t i;
  int data[] = { 1, 1, 1 };
  i = getlen(data, sizeof(data), 0);
  data[i] = userdata;
}

Implementation Details (GCC)

Violating this rule can have unexpected consequences, as in the following example:

Code Block
bgColor#ffcccc
langc
#include <stdio.h>

size_t getlen(const int *input, size_t maxlen, int delim) {
  for (size_t i = 0; i < maxlen; ++i) {
    if (input[i] == delim) {
      return i;
    }
  }
}

int main(int argc, char **argv) {
  size_t i;
  int data[] = { 1, 1, 1 };

  i = getlen(data, sizeof(data), 0);
  printf("Returned: %zu\n", i);
  data[i] = 0;

  return 0;
}

When this program is compiled with -Wall on most versions of the GCC compiler, the following warning is generated:

Code Block

Implementation Details

When this noncompliant code example is compiled with /-Wall on most versions of the GCC compiler,

Code Block
bgColor#ccccff

#include <stdio.h>

int main(void) {
  printf("test\n");
}

the following warning is generated

Code Block
bgColor#ccccff

example.c: In function ‘main’'getlen':
example.c:512: warning: control reaches end of non-void function

None of the inputs to the function equal the delimiter, so when run with GCC 5.3 on Linux, control reaches the end of the getlen() function, which is undefined behavior and in this test returns 3, causing an out-of-bounds write to the data array.

Compliant Solution

This compliant solution ensures that control never reaches the end of the checkpass function.changes the interface of getlen() to store the result in a user-provided pointer and returns a status indicator to report success or failure. The best method for handling this type of error is specific to the application and the type of error. (See ERR00-C. Adopt and implement a consistent and comprehensive error-handling policy for more on error handling.)

Code Block
bgColor#ccccff
langc
#include <stddef.h>
 
int checkpass(char *passwordgetlen(const int *input, size_t maxlen, int delim,
           size_t *result) {
  if (result == NULL) {
    return -1;
  }
  for (size_t i = 0; i < maxlen; ++i) {
    if (input[i] == delim) {
      *result = i;
      return 0;
    }
  }
  return -1;
}

void func(int userdata) {
  size_t i;
  int data[] = {1, 1, 1};
  if (getlen(data, sizeof(data), 0, &i) != 0) {
    /* Handle error */
  } else {
    data[i] = userdata;
  }
}

Exceptions

MSC37-C-EX1: According to the C Standard, 5.1.2.3.4, paragraph 1 [ISO/IEC 9899:2024], "Reaching the } that terminates the main function returns a value of 0." As a result, it is permissible for control to reach the end of the main() function without executing a return statement.

MSC37-C-EX2: It is permissible for a control path to not return a value if that code path is never taken and a function marked _Noreturn is called as part of that code path. For example:

Code Block
bgColor#ccccff
langc
#include <stdio.h>
#include <stdlib.h>
 
_Noreturn void unreachable(const char *msg)strcmp(password, "pass") == 0) {
    return 1;
  }
  return 0;
}
/* ... */
if (checkpass(userinput)) {
  printf("Success!Unreachable code reached: %s\n", msg);
  exit(1);
}

enum E {
  One,
  Two,
  Three
};
 
int f(enum E e) {
  switch (e) {
  case One: return 1;
  case Two: return 2;
  case Three: return 3;
  }
  unreachable("Can never get here");
}

Risk Assessment

Using the return value from a non-void function where control reaches the end of the function without evaluating a return statement can lead to buffer overflow vulnerabilities as well as other unexpected program behavior, and possibly abnormal program terminationbehaviors.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC37-C

medium

High

unlikely

Unlikely

low

Low

P6

P9

L2

References

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Automated Detection

ToolVersionCheckerDescription
Astrée
Include Page
Astrée_V
Astrée_V
return-implicitFully checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-MSC37
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V
LANG.STRUCT.MRSMissing return statement
Coverity
Include Page
Coverity_V
Coverity_V

MISSING_RETURN

Implemented
Cppcheck

Include Page
Cppcheck_V
Cppcheck_V

missingReturnFully implemented
Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

missingReturnFully implemented
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C++4022

DF2888


Klocwork
Include Page
Klocwork_V
Klocwork_V
FUNCRET.GEN
FUNCRET.IMPLICIT

LDRA tool suite
Include Page
LDRA_V
LDRA_V
2 D, 36 S, 66 SFully implemented
Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-MSC37-a

All exit paths from a function, except main(), with non-void return type shall have an explicit return statement with an expression
PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

533

Fully supported

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule MSC37-CChecks for missing return statement (rule fully covered)


RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
return-implicitFully checked
SonarQube C/C++ Plugin

Include Page
SonarQube C/C++ Plugin_V
SonarQube C/C++ Plugin_V

S935
TrustInSoft Analyzer

Include Page
TrustInSoft Analyzer_V
TrustInSoft Analyzer_V

Body of function falls-throughExhaustively verified.

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CERT C Secure Coding StandardMSC01-C. Strive for logical completenessPrior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11CWE-7582017-07-07: CERT: Rule subset of CWE

CERT-CWE Mapping Notes

Key here for mapping notes

CWE-758 and MSC37-C

Independent( INT34-C, INT36-C, MEM30-C, MSC37-C, FLP32-C, EXP33-C, EXP30-C, ERR34-C, ARR32-C)

CWE-758 = Union( MSC37-C, list) where list =

Undefined behavior that results from anything other than failing to return a value from a function that expects one

Bibliography

[ISO/IEC 9899:2024]5.1.2.3.4, "Program Termination"


...

Image Added Image Added Image Added Wiki Markup\[[ISO/IEC 9899:1999|AA. References#ISO/IEC 9899-1999]\] Section 6.9.1, "Function definitions"