Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

If control reaches the closing curly brace ('}') of a non-void nonvoid function without evaluating a return statement, using the return value of the function call causes undefined behavior. See undefined behavior 82 88 in Annex J.2.

This rule is related to recommendation MSC01-C. Strive for logical completeness because both practices are intended to ensure that programs properly handle all possible conditions.

...

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 undefined behavior, and various compilers generate code equivalent to the checkpass function, returning various values when no return statement is executed in checkpass().

Code Block
bgColor#ffcccc
langc

int checkpass(char *password) {
  if (strcmp(password, "pass") == 0) {
    return 1;
  }
}

/* ... */
if (checkpass(userinput)) {
  printf("Success\n");
}

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

...

Code Block
bgColor#ccccff
langc

int checkpass(char *password) {
  if (strcmp(password, "pass") == 0) {
    return 1;
  }
  return 0;
}

/* ... */
if (checkpass(userinput)) {
  printf("Success!\n");
}

...

In this noncomplaint code example, control reaches the end of the 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, this can lead to a buffer overflow may occur.

Code Block
bgColor#ffcccc
langc

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

/* ... */
size_t i;
int data[] = {1, 1, 1};
i = getlen(data, sizeof(data), 0);
data[i] = userdata;

...

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

Code Block

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

...

Code Block
bgColor#ffcccc
langc

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

size_t getlen(int *input, size_t maxlen, int delim) {
  size_t i;
  for (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: %d\n", i);
data[i] = 0;

return EXIT_SUCCESS;

...

This compliant solution changes the interface of getlen() to store the result in a user-provided pointer and return an error code to indicate any error conditions. The best method for handling this type of error is specific to the application and the type of error. (See recommendation ERR00-C. Adopt and implement a consistent and comprehensive error-handling policy for more on error handling.)

Code Block
bgColor#ccccff
langc

int getlen(int *input, size_t maxlen, int delim, size_t *result) {
  size_t i;
  for (i = 0; i < maxlen; ++i) {
    if (input[i] == delim) {
      if (result != NULL) {
        *result = i;
      }
      return 0;
    }
  }
  return -1;
}

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

...

Using the return value from a non-void nonvoid function where control reaches the end of the function can potentially lead to a buffer overflow vulnerability , as well as other unexpected program behaviors.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC37-C

high

unlikely

low

P9

L2

Related Guidelines

ISO/IEC 9899:1999 Section 2011 Section 6.9.1, "Function definitions"

...

 

...