CertC-DCL12ΒΆ
Implement abstract data types using opaque types
Required inputs: IR
Abstract data types are not restricted to object-oriented languages such as C++ and Java. They should be created and used in C language programs as well. Abstract data types are most effective when used with private (opaque) data types and information hiding.
Noncompliant Code Example
This noncompliant code example is based on the managed string library developed
by CERT [
Burch
2006]. In this example, the managed string type and the functions that
operate on this type are defined in the
string_m.h header file as follows:
struct string_mx {
size_t size;
size_t maxsize;
unsigned char strtype;
char *cstr;
};
typedef struct string_mx string_mx;
/* Function declarations */
extern errno_t strcpy_m(string_mx *s1, const string_mx *s2);
extern errno_t strcat_m(string_mx *s1, const string_mx *s2);
/* ... */
The implementation of the
string_mx type is fully visible to the user of the data type after
including the
string_m.h file. Programmers are consequently more likely to
directly manipulate the fields within the structure, violating the software
engineering principles of information hiding and data encapsulation and
increasing the probability of developing incorrect or nonportable code.
Compliant Solution
This compliant solution reimplements the
string_mx type as a private type, hiding the implementation of the
data type from the user of the managed string library. To accomplish this, the
developer of the private data type creates two header files: an external
string_m.h header file that is included by the user of the data
type and an internal file that is included only in files that implement the
managed string abstract data type.
In the external
string_m.h file, the
string_mx type is defined to be an instance of
struct string_mx, which in turn is declared as an
incomplete
type:
struct string_mx; typedef struct string_mx string_mx; /* Function declarations */ extern errno_t strcpy_m(string_mx *s1, const string_mx *s2); extern errno_t strcat_m(string_mx *s1, const string_mx *s2); /* ... */
In the internal header file,
struct string_mx is fully defined but not visible to a user of the
data abstraction:
struct string_mx {
size_t size;
size_t maxsize;
unsigned char strtype;
char *cstr;
};
Modules that implement the abstract data type include both the external and
internal definitions, whereas users of the data abstraction include only
the external
string_m.h file. This allows the implementation of the
string_mx data type to remain private.
Risk Assessment
The use of opaque abstract data types, though not essential to secure programming, can significantly reduce the number of defects and vulnerabilities introduced in code, particularly during ongoing maintenance.
| Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| DCL12-C | Low | Unlikely | High | P1 | L3 |
Related Guidelines
| MISRA C:2012 | Directive 4.8 (advisory) |
Bibliography
| [ Burch 2006] |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
composite_can_be_opaque |
Implementation of composite type should be hidden from unit(s). |
None |
False |
Options
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
This rule has no individual options.