Вивчай
· 5 хв читання
початківцямпоради

Найдорожчі баги в історії — 8 помилок, що коштували мільярди

Архівне чорно-біле фото зали керування з рядами консолей і моніторів, інженери за пультамиАрхівне чорно-біле фото зали керування з рядами консолей і моніторів, інженери за пультами

4 червня 1996 року ракета Ariane 5 стартувала з космодрому Куру. Через 37 секунд вона розвернулась на 90 градусів, почала розвалюватись від аеродинамічного навантаження і самознищилась. Разом із чотирма науковими супутниками. Збитки — близько $370 мільйонів.

Причина — одна операція: 64-бітне число з плаваючою комою запхали в 16-бітну цілу змінну. Число не влізло.

Про такі історії варто знати не заради жаху, а тому що кожна з них — це урок, який дехто вивчив за сотні мільйонів. Тобі він дістанеться безкоштовно.

1. Therac-25 — коли баг убиває (1985–1987)

Найстрашніший пункт у списку, і саме тому перший.

Therac-25 — апарат для променевої терапії. Попередні моделі мали апаратні запобіжники: фізичні блокування, які не давали увімкнути потужний пучок без захисної пластини. У Therac-25 їх прибрали — «програма сама все контролює».

Програма містила race condition: якщо оператор швидко правив параметри на клавіатурі, дві частини коду сперечалися за спільну змінну. Апарат видавав дозу, у сто разів більшу за призначену. Шість людей отримали передозування, троє померли. Виробник півтора року відповідав, що «передозування неможливе».

Урок: «код працює» і «код безпечний» — різні речі. І ніколи не прибирай запобіжник лише тому, що програма «сама розбереться».

2. Pentium FDIV — $475 мільйонів за чотири помилки в таблиці (1994)

Intel Pentium ділив числа неправильно. Не завжди — приблизно раз на 9 мільярдів ділень — але неправильно. Причина: у таблиці для алгоритму ділення з 1066 комірок п'ять були порожніми через помилку у скрипті, що її генерував.

Intel спершу відмовлялася міняти процесори всім підряд — «звичайний користувач зіткнеться з цим раз на 27 000 років». Публіка відреагувала так, що через місяць компанія оголосила повний відкликання і списала $475 мільйонів.

Урок: «майже ніколи» помножене на мільйони користувачів — це «щодня». І репутаційна вартість замовчування завжди вища за вартість виправлення.

3. Ariane 5 — переповнення, якого ніхто не перевіряв (1996)

Повернімося до ракети. Код, що впав, узяли з Ariane 4 — там він працював роками. Але Ariane 5 летіла швидше, і величина горизонтальної швидкості перевищила 32 767 — максимум для 16-бітного числа. Виникло виключення, бортовий комп'ютер вимкнувся, резервний — з тим самим кодом — теж.

Найгірше: цей фрагмент коду на Ariane 5 узагалі не був потрібен після старту. Він лишався в роботі «про всяк випадок».

Урок: код, перевірений в одних умовах, не перевірений у інших. І мертвий код — не безпечний код, а міна.

4. Mars Climate Orbiter — фунти проти ньютонів ($327 млн, 1999)

Апарат NASA долетів до Марса й згорів в атмосфері, бо зайшов на орбіту на 100 кілометрів нижче, ніж планувалось.

Команда Lockheed Martin писала програму, яка видавала імпульс у фунт-силах на секунду. Команда NASA читала ці числа як ньютон-секунди. Різниця — у 4,45 раза. Дев'ять місяців польоту кожна корекція курсу вносилась із помилкою, і ніхто не помітив.

Урок: одиниці виміру — частина даних, а не документації. Якщо функція приймає «число», рано чи пізно хтось передасть не те число. Назви змінну thrustNewtonSeconds, а не thrust.

5. Knight Capital — $440 мільйонів за 45 хвилин (2012)

Найшвидша втрата грошей в історії програмування.

Knight Capital — торгова компанія. Готуючи оновлення, інженери повторно використали старий прапорець у коді, який раніше вмикав тестовий модуль Power Peg — той навмисно купував дорого й продавав дешево, щоб перевіряти систему. Модуль давно не використовувався, але з коду його не видалили.

Оновлення розгорнули на восьми серверах. На семи. Восьмий пропустили. Коли торги відкрились, сім серверів працювали правильно, а восьмий побачив старий прапорець, увімкнув Power Peg і почав по-справжньому купувати дорого й продавати дешево. Мільйони разів. За 45 хвилин компанія втратила $440 мільйонів — і перестала існувати як незалежний бізнес.

Урок: видаляй мертвий код. Не перевикористовуй старі прапорці. Автоматизуй деплой — людина, яка розгортає на вісім серверів руками, пропустить восьмий.

6. Heartbleed — два рядки, які відкрили пів інтернету (2014)

OpenSSL — бібліотека, що шифрує з'єднання майже на всіх сайтах світу. У ній була функція heartbeat: клієнт надсилає «ось 5 байт, поверни мені їх», сервер повертає.

Тільки сервер не перевіряв, чи справді надіслано 5 байт. Клієнт міг сказати «ось 5 байт, поверни 65 000» — і сервер слухняно віддавав 65 000 байт зі своєї пам'яті. Там лежали паролі, ключі шифрування, сесії інших користувачів. Вразливість жила в коді два роки і зачепила близько 17% захищених серверів світу.

Виправлення — перевірка довжини. Два рядки.

Урок: ніколи не довіряй довжині, яку прислав клієнт. Валідуй усе, що приходить ззовні — це правило номер один у будь-якій роботі з API.

7. left-pad — 11 рядків, що зупинили npm (2016)

Розробник видалив із npm свій пакет left-pad — функцію з 11 рядків, яка додає пробіли зліва від рядка. Через конфлікт із компанією щодо назви іншого пакета.

Виявилось, що від цих 11 рядків залежали Babel, React, Node-проєкти по всьому світу. Тисячі збірок упали за кілька хвилин. npm довелося вперше в історії примусово відновити чужий пакет.

Урок: кожна залежність — це довіра до незнайомої людини. Перед тим як ставити пакет заради однієї функції, спитай, чи не швидше написати її самому.

8. CrowdStrike — 8,5 мільйона синіх екранів за годину (2024)

19 липня 2024 року компанія CrowdStrike розіслала оновлення конфігурації для свого захисного ПЗ. Файл містив помилку, через яку драйвер читав пам'ять за неправильною адресою. Драйвер працював на рівні ядра Windows — тож комп'ютер не міг навіть завантажитись.

Приблизно 8,5 мільйона машин по всьому світу впали в синій екран. Аеропорти, лікарні, банки, служби 911. За оцінкою страхової Parametrix, лише компанії зі списку Fortune 500 втратили $5,4 мільярда. Відновлення вимагало фізичного доступу до кожного комп'ютера.

Тест, який мав зловити помилку, теж містив баг — і позначив зламаний файл як справний. Оновлення вийшло на всіх одразу, без поетапного розгортання.

Урок: розгортай поступово — спочатку 1%, потім 10%, потім усі. Одна помилка на 1% користувачів — інцидент; на 100% — катастрофа.

Що спільного в усіх восьми

Зверни увагу: жодна з цих помилок не була складною. Переповнення числа. Неперевірена довжина. Забутий прапорець. Не та одиниця виміру. Пропущений сервер.

Це ті самі помилки, які ти зробиш у своєму першому проєкті — і це нормально. Різниця лише в ціні: у тебе вона нульова, у них — сотні мільйонів.

Тому вчися робити їх зараз, поки безкоштовно. Пиши перевірки на вхідні дані, навіть коли «і так зрозуміло». Видаляй код, який не використовується. Називай змінні так, щоб одиниці були в назві. І ніколи не кажи «цього не може статися» — саме ця фраза стоїть на початку кожної історії вище.