You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 17 Next »

If control reaches the end of a non-void function, using the return value of the function call results in undefined behavior. See also undefined behavior 7 of Appendix J.

This rule is related to rule MSC01-C. Strive for logical completeness because both rules involve ensuring that programs properly handle all possible conditions.

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

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 guideline MSC00-C. Compile cleanly at high warning levels.)

Compliant Solution

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

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

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

Noncompliant Code Example

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

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;

Implementation Details

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

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

When the program was compiled and run with GCC 4.4.3 on Linux, the getlen() function returned 5, causing an out-of-bounds write to the data array:

#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;

Compliant Solution

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 guideline ERR00-C. Adopt and implement a consistent and comprehensive error-handling policy for more on error handling.)

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;
}

Risk Assessment

Using the return value from a non-void 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

Bibliography

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


MSC36-C. Check for alignment of memory space before calling realloc() function      49. Miscellaneous (MSC)      MSC38-C. Do not treat as an object any predefined identifier that might be implemented as a macro

  • No labels