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

Compare with Current View Page History

« Previous Version 35 Next »

Calling a function with incorrect arguments can result in unexpected or unintended program behavior. Functions that are appropriately declared [[DCL07-A. Include the appropriate type information in function declarators]] will typically fail compilation if they are supplied with the wrong number or types of arguments. However, there are cases where supplying the incorrect arguments to a function will only generate compiler warnings. These warnings should be resolved [[MSC00-A. Compile cleanly at high warning levels]], but do not prevent program compilation.

Non-Compliant Code Example: (function pointers)

In this example, the function pointer fp is used to refer to the function strchr(). However, fp is defined without the appropriate parameter list. As a result there is no type checking performed on the call to fp(12,2);.

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

char *(*fp) ();

int main(void) {
  char *c;
  fp = strchr;
  c = fp(12, 2);
  printf("%s\n", c);

}

Note that this example violates recommendation [[DCL35-C. Do not convert a function pointer to a function of an incompatible type]].

Compliant Solution: (function pointers)

Properly declaring fp so it is compatible with strchr() corrects this example.

#include <string.h>

char *(*fp) (char const *, int);

int main(void) {
  char *c;
  fp = strchr;
  c = fp("Hello",'H');
  printf("%s\n", c);

}

Non-Compliant Code Example: (variadic functions)

The POSIX function open() [[Open Group 04]] is a variadic function with the following prototype:

int open(char const *path, int oflag, ... );

The open() function accepts a third argument to determine a newly created file's access mode. If open() is used to create a new file and the third argument is omitted, the file may be created with unintended access permissions [[FIO06-A. Create files with appropriate access permissions]].

/* ... */
int fd = open(file_name, O_CREAT | O_WRONLY); /* access permissions are missing */
if (fd == -1){
  /* Handle Error */
}
/* ... */

Compliant Solution: (variadic functions)

To correct this example, a third argument is specified in the call to open().

/* ... */
int fd = open(file_name, O_CREAT | O_WRONLY, file_access_permissions);
if (fd == -1){
  /* Handle Error */
}
/* ... */

Non-Compliant Code Example (argument validation)

Using a user-defined function to calculate the amount of memory to allocate is a common practice that may sometimes be necessary. However, if the function used to calculate the size parameter is flawed, then an incorrect size argument will be supplied to the allocation routine.

This following non-compliant code reads user-supplied data from standard input, returning the number of characters read.

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

enum { MAXLINE = 1000 };

size_t calc() {
  char line[MAXLINE], c;
  size_t size = 0;
  while ( (c = getchar()) != EOF && c != '\n') {
    line[size] = c;
    size++;
    if (size >= MAXLINE)
      break;
  }
  return size;
}

int main(void) {
  char *line = malloc(calc());
  if (line == NULL) {
    /* Handle malloc() error */
  }
  /* ... */
  free(line);
}

However, if no characters are entered, calc() will return 0. Because there is no validation on the result of calc(), a malloc(0) [[MEM04-A. Do not make assumptions about the result of allocating 0 bytes]] could occur, which could lead to a buffer overflow.

Compliant Solution (argument validation)

In this compliant solution, the result of calc() is not supplied directly to malloc(). Instead, the result of calc() is stored in the variable size and checked for the exceptional condition of being 0. This modification reduces the complexity of the line of code that calls malloc() and adds an additional layer of validation, thus reducing the chances of error.

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

enum { MAXLINE = 1000 };

size_t calc() {
  char line[MAXLINE], c;
  size_t size = 0;
  while ( (c = getchar()) != EOF && c != '\n') {
    line[size] = c;
    size++;
    if (size >= MAXLINE)
      break;
  }
  return size;
}

int main(void) {
  size_t size = calc();
  if (!size) {
    /* Handle invalid size */
  }
  char *line = malloc(size)
  if (line == NULL) {
    /* Handle malloc() error */
  }
  /* ... */
  free(line);
}

Risk Assessment

Calling a function with incorrect arguments can result in unexpected or unintended program behavior.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXP37-C

1 (low)

1 (unlikely)

3 (low)

P3

L3

Related Vulnerabilities

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

References

[[ISO/IEC 9899-1999]] Forward, Section 6.9.1, "Function definitions"
[[Spinellis 06]] Section 2.6.1, "Incorrect Routine or Arguments"

  • No labels