Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The logical AND and logical OR operators (&& and ||, respectively) exhibit "short circuit" operation. That is, the second operand is not evaluated if the result can be deduced solely by evaluating the first operand. Consequently,

One should exercise caution if the second operand should not contain contains side effects because it would may not be apparent whether the side effect occurs.

...

effects actually occur.

In the following non-compliant code, the value of i is incremented only when i >= 0.

#FFCCCC
Code Block
bgColor
enum { max = 15 };
int i = /* initialize to user supplied value */;

if ( (i >= 0) && ( (i++) <= max) ) {
  /* code */
}

Although the behavior is well-defined, it is not immediately obvious how this code behaves.

Compliant Solution

This compliant solution exhibits identical behavior but is easier to understand.

Code Block
bgColor#ccccff

enum { max = 15 };
int i = /* initialize to user supplied value */;

if (i >= 0) {
  i++;
  if  (i <= max) {
    /* code */
  }
}

whether i gets incremented or not.

Non-Compliant Code Example

In this non-compliant code example, the second operand of the logical OR operator invokes a function that results in side effects.

#FFCCCC
Code Block
bgColor
char *p; = /* initialize, may or may not be NULL */

if ( p || (p = (char *) malloc(BUF_SIZE)) ) {
  /* do stuff with p */
  free( p);
}
else {
  /* handle malloc() error */
   return;
}

Since malloc() is only called if p is NULL when entering the if clause, the call to {[free()}} might be receiving a pointer to local data not allocated by malloc(). This is partially due to the uncertainty of whether malloc() is actually called or not.

Compliant Solution

This compliant solution exhibits identical behavior but is easier to understandIn this compliant solution, a second pointer, q is used to indicate whether malloc() is called; if not, q remains set to NULL. Passing NULL to free() is guaranteed to safely do nothing.

Code Block
bgColor#ccccff
char *p;
char *q = NULL;
if (p == NULL) {
 p q = (char *) malloc(BUF_SIZE);
  p = q;
}
if (p == NULL) {
  /* handle malloc() error */
  return;
}

/* do stuff with p */
free(q);

Risk Assessment

Attempting to modify an object that is the second operand to Failing to understand the short-cirtuit behavior of the logical OR or AND operator may cause that object to take on an unexpected value. This can lead to unintended program behavior.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

EXP02-A

low

unlikely

medium

P2

L3

Automated Detection

The LDRA tool suite V 7.6.0 is able to detect violations of this recommendation.

Related Vulnerabilities

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

References

Wiki Markup
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.5.13, "Logical AND operator," and Section 6.5.14, "Logical OR operator"

...