Using type definitions (typedef
) can often improve code readability. However, type definitions to pointer types can make it more difficult to write const
-correct code because the const
qualifier will be applied to the pointer type, not to the underlying declared type.
The following type definition improves readability at the expense of introducing a const
-correctness issue. In this example, the const
qualifier applies to the typedef
instead of to the underlying object type. Consequently, func
does not take a pointer to a const struct obj
but instead takes a const
pointer to a struct obj
.
struct obj { int i; float f; }; typedef struct obj *ObjectPtr; void func(const ObjectPtr o) { /* Can actually modify o's contents, against expectations */ } |
This compliant solution makes use of type definitions but does not declare a pointer type and so cannot be used in a const
-incorrect manner:
struct obj { int i; float f; }; typedef struct obj Object; void func(const Object *o) { /* Cannot modify o's contents */ } |
The Win32 SDK headers make use of type definitions for most of the types involved in Win32 APIs, but this noncompliant code example demonstrates a const
-correctness bug:
#include <Windows.h> /* typedef char *LPSTR; */ void func(const LPSTR str) { /* Can mutate str's contents, against expectations */ } |
This compliant solution demonstrates a common naming convention found in the Win32 APIs, using the proper const
type:
#include <Windows.h> /* typedef const char *LPCSTR; */ void func(LPCSTR str) { /* Cannot modify str's contents */ } |
Note that many structures in the Win32 API are declared with pointer type definitions but not pointer-to-const
type definitions (LPPOINT
, LPSIZE
, and others). In these cases, it is suggested that you create your own type definition from the base structure type.
#include <Windows.h> /* typedef struct tagPOINT { long x, y; } POINT, *LPPOINT; */ void func(const LPPOINT pt) { /* Can modify pt's contents, against expectations */ } |
#include <Windows.h> /* typedef struct tagPOINT { long x, y; } POINT, *LPPOINT; */ typedef const POINT *LPCPOINT; void func(LPCPOINT pt) { /* Cannot modify pt's contents */ } |
In this noncompliant code example, the declaration of the signal()
function is difficult to read and comprehend:
void (*signal(int, void (*)(int)))(int); |
This compliant solution makes use of type definitions to specify the same type as in the noncompliant code example:
typedef void SighandlerType(int signum); extern SighandlerType *signal( int signum, SighandlerType *handler ); |
Function pointer types are an exception to this recommendation.
Code readability is important for discovering and eliminating vulnerabilities.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL05-C | Low | Unlikely | Medium | P2 | L3 |
Tool | Version | Checker | Description |
---|---|---|---|
Astrée | pointer-typedef | Fully checked | |
Axivion Bauhaus Suite | CertC-DCL05 | ||
CodeSonar | LANG.STRUCT.PIT | Pointer type inside typedef | |
Compass/ROSE | |||
Helix QAC | C5004 | ||
LDRA tool suite | 299 S | Partially implemented | |
Parasoft C/C++test | CERT_C-DCL05-a | Declare a type of parameter as typedef to pointer to const if the pointer is not used to modify the addressed object | |
RuleChecker | pointer-typedef | Fully checked |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
CERT C Secure Coding Standard | DCL12-C. Implement abstract data types using opaque types |
SEI CERT C++ Coding Standard | VOID DCL05-CPP. Use typedefs to improve code readability |