Lecture
A gotcha ( English Gotcha ) in programming denotes a valid construct in a programming language or system that works as documented but is counterintuitive and often leads to errors, because it is easy to invoke while the result is unexpected
In programming, a gotcha is a valid construct in a system, program, or programming language that works as documented but is counterintuitive and almost invites errors, because it is so easy to trigger and its outcome is unexpected or unjustified.
A classic pitfall in C / C++ is the construct
if( a = b ) {...};
It is syntactically valid: it places the value of binto aand then executes codeif ais not equal to zero. Sometimes this is even intended. However, more often it is a typo: the programmer probably meant
if ( a == b ) {...};
which executes codeif aand bare equal. Modern compilers usually generate a warning when they detect the first construct (a conditional branch on an assignment rather than a comparison), depending on the compiler options (for example, the -Wall option for gcc). To avoid this error, it is recommended to keep constants on the left-hand side of the comparison, for example, 42 == x rather than x == 42. This way, using =instead of ==will cause a compiler error (see Yoda conditions). However, many kinds of errors are not detected by compilers. .
Yoda conditions (from English Yoda conditions), or Yoda notation (English Yoda notation) in programmer jargon — a «safe» style of writing comparison expressions when programming in languages with C syntax, consisting of writing the constant member of the expression (a constant or a function call) to the left of the comparison operator (that is, 5 == a instead of the customary a == 5).
This style is intended to prevent an error inherent to these languages — the use of the assignment operator «=» instead of the comparison «==». An erroneous use of assignment turns Yoda notation into an attempt to modify a constant, causing an error at compile time, which rules out the possibility of this kind of error appearing in the finished program, and also makes it easier to find and fix them in new code.
The notation is named after Master Yoda from the «Star Wars» universe, who has a manner of arranging the words of a phrase in reverse order.
In classic notation, checking a variable for equality with some constant is written as follows (example in the PHP language):
if ( $variable == 52 ) {
/* actions performed if the variable equals 52 */
}
that is, a variable, a comparison operation, and a constant. This construct is vulnerable to a well-known error:
if ( $variable = 52 ) { // ERROR: ASSIGNING the value 52 to the variable
/* actions performed ALWAYS, since the value of the expression in parentheses will be the number 52, which is not equal to zero and is therefore treated as true in this context */
}
Such code remains syntactically correct, and with inadequate testing it can remain in a program for many years and become the cause of a serious vulnerability.
When using Yoda notation, the variable and the constant swap places, so that the constant ends up on the left:
if ( 52 == $variable ) {
/* actions performed if the variable equals 52 */
}
With such notation, in the event of a typo in the comparison operator, you get a syntactically incorrect assignment to a constant, and the program will not work until the error is found and fixed.
if ( 52 = $variable ) { // ERROR at compile time
/* ... */
}
Exactly the same applies to functions:
if ( someFunction() = $variable ) { // ERROR at compile time /* ... */ }
Yoda notation is also applicable in resolving the problem of «unsafe null behavior» (English unsafe null behavior), for example (example in the Java language):
String myString = null;
if ( myString.equals("foobar") ) { // Throws a NullPointerException
/* ... */
}
When applying Yoda notation:
String myString = null;
if ( "foobar".equals(myString) ) { // Result is False
/* not executed */
}
The use of Yoda notation prevents programs in C++, Java, PHP, and other languages from working when there are errors in comparison expressions (this modification does not change the program's behavior). Some programmers consider the use of this notation «a sign of good manners» .
Among the disadvantages of the notation are the difficulty of writing, modifying, and reading the program , as well as a rather narrow area of application — only equality comparison, only comparison with a constant or the result of a function call. Modern development tools (compilers, editors) make it possible to track and issue warnings when they encounter an assignment inside a control construct, considering it potentially erroneous.
sys_wait4() bug[ Notable is the failed attempt to plant a backdoor in the sys_wait4() function in the Linux kernel (2003) . Development was carried out on the proprietary version control system BitKeeper, and at night the code was uploaded to the more widely used CVS. It was this CVS that was hacked, adding to the sys_wait4() system call handler code that looked as if it were checking the input data for an invalid combination of flags:
+ if ((options == (__WCLONE|__WALL)) && (current->uid = 0)) + retval = -EINVAL;
The backdoor was disguised as a simple typo — instead of == there was =. Thus, passing two mutually contradictory flags to the function executed the code current->uid = 0, that is, it gave the program superuser privileges.
The next pull of information to CVS failed, and the foreign patches were removed before it became clear what they were. The patch could not make it into the stable kernel (the link between BitKeeper and CVS is one-way). The author of the backdoor could not be found.
Comments