Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Removed references to Annex K.

Functions Related functions, such as those that make up a library, should provide consistent and usable error checking mechanism. Complex interfaces can be misunderstood or disregarded by programmers, resulting in code that is not error checked. Inconsistent interfaces are difficult to use as the programmer must constantly refer to documentation to determine how the function indicates errors resulting in higher development costs. Failure to ensure that a function call is correctly error checked can result in errors and possible vulnerabilitiesinterfaces. Ralph Waldo Emerson said, "A foolish consistency is the hobgoblin of little minds," but inconsistencies in functional interfaces or behavior can lead to erroneous use, so we understand this to be a "wise consistency." One aspect of providing a consistent interface is to provide a consistent and usable error-checking mechanism. For more information, see API04-C. Provide a consistent and usable error-checking mechanism.

Noncompliant Code Example (

...

Interface)

The strlcpy() function copies a null-terminated source string to a destination array. It is designed to be safer, more consistent, and less error prone replacements for strcpy().

The strlcpy() function returns the total length of the string it tried to create (the length of the source string).

To detect truncation, perhaps while building a pathname, something like the following might be usedIt is not necessary to go beyond the standard C library to find examples of inconsistent interfaces: the standard library is a fusion of multiple libraries with various styles and levels of rigor. For example, the fputs() defined in the C Standard, subclause 7.21.7.4, is closely related to the fprintf() defined in subclause 7.21.6.1. However, fputs()'s file handle is at the end, and fprintf()'s is at the beginning, as shown by their function declarations:

Code Block
bgColor#FFcccc
langc
int fputs(const 
char *dir, restrict s, FILE *file, pname[MAXPATHLEN] restrict stream);

/* ...int fprintf(FILE */

if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname)) {
  /* handle source string too long error */
}

Compliant Solution (strcpy_m())

The managed string library handles errors by consistently returning the status code in the function return value. This approach encourages status checking because the user can insert the function call as the expression in an if statement and take appropriate action on failure.

The strcpy_m() function is an example of a managed string function that copies a source managed string into a destination managed string.

Code Block
bgColor#ccccff

errno_t retValue; 
string_m dest, source;  

/* ... */

if (retValue = strcpy_m(dest, source)) { 
  fprintf(stderr, "Error %d from strcreate_m.\n", retValue);
} 

The greatest disadvantage of this approach is that it prevents functions from returning any other value. This means that all values (other than the status) returned by a function must be returned as a pass-by-reference parameter, preventing a programmer from nesting function calls. This tradeoff is necessary because nesting function calls can conflict with a programmer's willingness to check status codes.

Risk Assessment

 restrict stream, const char * restrict format, ...);

The argument order can be easily rearranged using macros; for example:

Code Block
bgColor#FFcccc
langc
#include <stdio.h>
#define fputs(X,Y) fputs(Y,X)

However, according to subclause 7.1.3 of the C Standard, the behavior of a program that defines a symbol, including a macro, with the same name as that of a standard library function, type, macro, or other reserved identifier is undefined.

Using inconsistent interfaces makes the code difficult to read, for example, by causing confusion when moving between code that follows this convention and code that does not. In effect, it becomes impossible to modify an interface once that interface has been broadly adopted. Consequently, it is important to get the interface design right the first time.

Compliant Solution (Interface)

The POSIX threads library [Butenhof 1997] defines an interface that is both consistent and fits in with established conventions from the rest of the POSIX library. For example, all initialization functions follow the same consistent pattern of the first argument being a pointer to the object to initialize with the subsequent arguments, if any, optionally providing additional attributes for the initialization:

Code Block
bgColor#ccccff
langc
/* Initialization of pthread attribute objects */
int pthread_condattr_init(pthread_condattr_t *);
int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_rwlockattr_init(pthread_rwlockattr_t *);
...
/* Initialization of pthread objects using attributes */
int pthread_cond_init(pthread_cond_t * restrict, const pthread_condattr_t * restrict);
int pthread_mutex_init(pthread_mutex_t * restrict, const pthread_mutexattr_t * restrict);
int pthread_rwlock_init(pthread_rwlock_t * restrict, const pthread_rwlockattr_t * restrict);
...

Function arguments that refer to objects that are not modified are declared const. Because the object pointed to by the first argument is modified by the function, it is not const. For functions that implement a data abstraction, it is reasonable to define the handle for the data abstraction as the initial parameter. (See DCL12-C. Implement abstract data types using opaque types.) Finally, initialization functions that accept a pointer to an attribute object allow it to be NULL as an indication that a reasonable default should be used.

Noncompliant Code Example (Behavior)

The shared folder and file copy functions in the VMware virtual infrastructure (VIX) API are inconsistent in the set of characters they allow in folder names. As a result, you can create a shared folder that you subsequently cannot use in a file copy function such as VixVM_CopyFileFromHostToGuest().

Compliant Solution (Behavior)

Try to be consistent in the behavior of related functions that perform operations on common objects so that an object created or modified by one function can be successfully processed by a downstream invocation of a related function.

Risk Assessment

Failure to maintain consistency in interfaces and capabilities across functions can Failure to do so can result in type errors in the program.

Rule

Severity

Likelihood

Detectable

Remediation Cost

Repairable

Priority

Level

API04

API03-C

medium

Medium

Unlikely

unlikely

No

medium

No

P2

L3

Related Vulnerabilities

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

Other Languages

This rule appears in the C++ Secure Coding Standard as API04-CPP. Provide a consistent and usable error checking mechanism.

References

Wiki Markup
\[[Burch 06|AA. C References#Burch06]\]
\[[CERT 06c|AA. C References#CERT 06c]\]
\[[ISO/IEC 9945:2003|AA. C References#ISO/IEC 9945-2003]\]
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.21, "String handling <{{string.h}}>"
\[[ISO/IEC 23360-1:2006|AA. C References#ISO/IEC 23360-1-2006]\]
\[[ISO/IEC TR 24731-1:2007|AA. C References#ISO/IEC TR 24731-1-2007]\]
\[[ISO/IEC PDTR 24731-2|AA. C References#ISO/IEC PDTR 24731-2-2007]\]
\[[Miller 99|AA. C References#Miller 99]\]
\[[MISRA 04|AA. C References#MISRA 04]\] Rule 20.4
\[[Seacord 05a|AA. C References#Seacord 05a]\] Chapter 2, "Strings"


Automated Detection

Tool

Version

Checker

Description

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

ISO/IEC 9945:2003
Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC 23360-1:2006
Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TR 24731-2
Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 21.3 (required)Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Directive 4.12 (required)Prior to 2018-01-12: CERT: Unspecified Relationship

Bibliography


...

Image Added Image Added Image AddedImage Removed      01. Preprocessor (PRE)      02. Declarations and Initialization (DCL)