A nice example (for 16-bit implementation) is given in MISRA-C:2004, Rule 12.1:

uint16_t a = 10U;
uint16_t b = 65535U;
uint32_t c = 0U;
uint32_t d;

d = (a + b) + c; /* d is 9; a + b wraps modulo 65536 */
d = a + (b + c); /* d is 65545 */
/* this example also deviates from several other rules */

The guideline says:
"In addition to the use of parentheses to override default operator precedence, parentheses should also be used to emphasise it. It is easy to make a mistake with the rather complicated precedence rules of C, and this approach helps to avoid such errors, and helps to make the code easier to read. However, do not add too many parentheses so as to clutter the code and make it unreadable."

There is also Rule 12.5, that applies specifically to logical operators.
It says, that the operands of logical && or || shall be primary expressions. There is an exception that if there is a sequence of only logical && of only logical ||, then extra parentheses are not required.

Anyway, i know that MISRA-C is widely accepted in many industries for high integrity software development (namely aerospace, automotive, medical and railway), so i would follow these rules for maximum safety of my code.

MISRA-C has just got updated to MISRA-C:2012, so it might contain additional guidelines regarding parenthesis.

On Tue, 22 Oct 2013, Werner Almesberger wrote:

[ Came across a security-related article that made me think of an
 old and constant gripe of mine. Here's my rant, somewhat off-topic. ]

I've been on a crusade against redundant parentheses for a long time.
They often make it hard to read other people's work and obscure the
programmer's intentions.

A very common use of redundant parentheses in C occurs in Boolean
expressions, e.g.,

        if ((a > 10) || (a == 0))

The origin of such constructs my be Pascal. In Pascal, the Boolean
operators "and" and "or" have higher precedence than relational
operators. Therefore, in Pascal, all the parentheses in

        if ((a > 10) or (a = 0))

are required. Note that Pascal uses "=", not "==", to test for
equality.

C gives lower precedence to && and || than to relational operators
and we therefore don't need parentheses in this case:

        if (a > 10 || a == 0)

Clean and simple.

Programmers coming from a Pascal background may have brought these
parentheses to C, corrupted those improperly schooled in C operator
precedence, and thus caused this now widespread disease. If you
think of it, it's a bit like how the Black Death came to Europe.
[1]


So far, these things are widely known. Now, there's a twist:

Once upon a time, a malicious "bug" was introduced in the Linux
kernel that made use of this sloppy practice to hide its nefarious
purpose. While I didn't make the connection to redundant parentheses
back then, I recently read an article [2] that rehashed the topic,
and spotted the link this time. The code in question looked like
this:

        if ((options == (__WCLONE|__WALL)) && (current->uid = 0))

This is structurally equivalent to

        if ((a > 10) || (a = 0))

Note that the second expression is an assignment, not a comparison.
In the example above, the intent is to give a process root privileges
by setting current->uid to zero if there is a certain "magic" pattern
in the "options" argument.

"==" vs. "=" is a common typo in C and can produce nasty and hard to
find bugs. It is so common that modern C compilers warn when seeing
things like

        if (a = 0)

gcc -Wall:

 warning: suggest parentheses around assignment used as truth value

LLVM (clang) gives the following lecture:

 warning: using the result of an assignment as a condition without parenthese
 note: place parentheses around the assignment to silence this warning
 note: use '==' to turn this assignment into an equality comparison

As LLVM explains, the warning can be silenced by adding parentheses.
This works with both compilers:

        if ((a = 0))

Looks ugly and should serve as a hint that it's better to avoid this
sort of assignments entirely. E.g., instead of

        if ((a = EXPRESSION))
                ...

to write

        a = EXPRESSION;
        if (a)
                ...

Now, the double parentheses are easy to spot. But, given the
widespread bad practice of using redundant parentheses, it's much
harder to catch the assignment in the malicious case:

        if ((a > 10) || (a == 0))    /* ugly but common */

vs.

        if ((a > 10) || (a = 0))     /* evil */

This could of course also happen as the result of a normal typo. So
by using redundant parentheses, developers not only make their code
harder to read, they also defeat a mechanism that is there to protect
them from likely mistakes.

Let's see what would happen if using only the parentheses C requires:

        if (a > 10 || a = 0)
gcc:
 error: lvalue required as left operand of assignment
LLVM:
 error: expression is not assignable

Both are right - the expression now becomes the equivalent of

        if ((a > 10 || a) = 0)

and the left-hand side of the assignment makes no sense. That's also
why the malicious code really needed the parentheses: not only to
avoid a warning that may draw undesired attention, but to get the
code to compile at all.

But if the expressions were swapped, the code would be syntactically
valid:

        if (a = 10 || a > 10)

And now, the compiler's warning is the last line of defense.

- Werner

[1] http://en.wikipedia.org/wiki/Black_Death
[2] 
https://freedom-to-tinker.com/blog/felten/the-linux-backdoor-attempt-of-2003/

_______________________________________________
Qi Hardware Discussion List
Mail to list (members only): [email protected]
Subscribe or Unsubscribe: 
http://lists.en.qi-hardware.com/mailman/listinfo/discussion


_______________________________________________
Qi Hardware Discussion List
Mail to list (members only): [email protected]
Subscribe or Unsubscribe: 
http://lists.en.qi-hardware.com/mailman/listinfo/discussion

Reply via email to