Skip to end of metadata
Go to start of metadata

Naming the parameters in a prototype declaration should never be necessary, and is often unwise, because these names can be affected by macro definitions.

Although the scope of an identifier in a function prototype begins at its declaration and ends at the end of that function's declarator, this scope is ignored by the preprocessor. Consequently, an identifier in a prototype having the same name as that of an existing macro is treated as an invocation of that macro.

Safeguarding parameter names is particularly critical in standard and system headers where the user expects to be able to include the header and have only the function names visible.

Noncompliant Code Example

This noncompliant code example,

#define status 23
void update_status(int status);

generates an error, because the prototype, after preprocessing, becomes

void update_status(int 23);

Perhaps more surprising is what happens if status is defined:

#define status []

Then the resulting prototype is

void update_status(int []);

which is syntactically correct but semantically quite different from the intent.

Compliant Solution

To protect an API's header prototypes from such misinterpretation, the developer must write them to avoid these surprises. Possible solutions include not using identifiers in prototypes, as in this example:

void update_status(int);

Another solution is to comment them out, as in this example:

void update_status(int /* status */);

Comments are converted to a single whitespace character in translation phase two.

Risk Assessment

Failure to protect header prototypes from misinterpretation can result in type errors in the program.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

API08-C

Medium

Unlikely

Medium

P4

L3

Automated Detection

ToolVersionCheckerDescription
Astrée
19.04
named-declaration-parameterFully checked

ECLAIR

1.2

CC2.API08

Fully implemented

RuleChecker
19.04
named-declaration-parameterFully checked

Related Vulnerabilities

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

Bibliography



6 Comments

  1. Doesn't this conflict with API05-C ("Use conformant array parameters")?

    1. Technically API05-C. Use conformant array parameters violates this recommendation. That's OK, because they are both recommendations and not hard-and-fast rules.

  2. With regards to C++, isn't the violation in the "Noncompliant code" examples the defining of a macro, in violation of PRE00-CPP. "Avoid defining macros"? This seems to be the general consensus of the C++ ISO (e.g. Preprocessor is evil)

    Bjarne Stroustrup's 2014 "A Tour of C++" contains many examples with parameter names in a function prototype, as do many other ISO and non-ISO examples (e.g. Section 2.4 of the ISO's Tour, or see "Declaring Functions" in this Function tutuorial).

    Would it be preferable to limit this advise to C by tagging this recommendation as "not-for-cpp"?

     

    1. Technically, this also violates PRE00-C. Prefer inline or static functions to function-like macros as well.

      I don't believe this recommendation makes sense given the number of places identifiers are used where they cannot be elided, such as struct names, local variables, types, etc. I think this puts the burden on the wrong place – the recommendation should be to not write macros that will conflict with other identifiers, especially since macros are idem non grata. For instance, by recommending all macro names be in all caps, and other identifiers not be in all caps.

      C++ adds to the list of places where identifiers are required, such as template parameter lists, class base specifier lists, exception handler parameter lists, lambda parameter lists, etc, so this recommendation can't really apply in C++ without some work, which is why I am adding the not-for-cpp label.

      1. I think the NCCE meant to say something like "Suppose status is a macro with the following value, and you can't change it (though it violates several CERT rules and lots of convention). Then the following code does not mean what you think it means".

        I agree with Aaron...this rule should not exist; the fault lies with the macro, not with the function.

        AFAICT this is the same in both C++ and C, even if the C++ community is more against macros than C.

  3. This recommendation has high cost and low benefit. This reduces the readability of all function prototypes, thus increasing the chance of errors by API consumers. This only has benefit when macros are misused (and thus has zero benefit in good quality code). This rule is more likely to reduce security (due to API usage errors) than to increase it. I concur with others who believe this recommendation should be removed.