log_entry_042: Рейтинг, который не падает. Как число Пи сломало цифрового бога

Автор: Андрей Кварцев

Продолжаем разбор ИТ-концепций, спрятанных в тексте "Заговорённых".

https://author.today/work/509687

К моему удовольствию (и надеюсь, к вашему) пришло время для центральной вишенки сюжета. Собственно говоря, это и есть идея, из которой выросло всё произведение. Ошибка, обездвижившая систему и открывшая путь к её разрушению.

Как устроен рейтинг в мире «Заговорённых»

В реалиях романа РБЛ — целое число, которое хранится в базе данных, привязано к идентификатору гражданина и определяет всё: от калорий в пайке до права на жизнь.

Каждое действие гражданина — покупка, переход улицы, громкий разговор — анализируется системой. Если действие признаётся неблагонадёжным, система вычитает баллы. 

Здесь пока соблюдается классический принцип работы базы данных SQL: SELECT rating FROM citizens WHERE id = xxxx

По условиям мира нормальный рейтинг – четырёхзначное число. Если оно падает ниже 1000 (становится трёхзначным), то человек переходит в категорию деклассированных, если падает ниже нуля — ликвидируют. Простая, понятная механика. Работает для всех. Кроме одного.

Оператор Виэн — человек с аномалией. Его Рейтинг Благонадёжности (РБЛ) застыл на одной цифре. Он может нарушать правила: опаздывать на работу, заходить в закрытые директории, воровать синтетический квас из автомата. Система фиксирует нарушение, выписывает штраф — но рейтинг не меняется. Оператор является призраком для системы наказания.

В главе 22 сисадмин из прошлого находит истинную причину этой аномалии. Он залезает в сырые данные профиля Виэна и видит в поле RBL - мигающий индикатор 0x, а в RBL_raw_value: 3141.59265358979323846.., сопровождённый записью об ошибке ERROR: BUFFER OVERFLOW. CANNOT ASSIGN TO FIXED INT. IGNORING VALUE.

В поле рейтинга пытается записаться не целое число, а бесконечная дробь – число Пи.


Гонка состояний (race condition): как рождаются баги-призраки

Сисадмин объясняет это так:

Миллионы профилей создавались единовременно. В одном потоке им присваивались стандартные рейтинги — простые целые числа. В другом, параллельном потоке, ядро генерировало сложнейшие криптографические ключи для самозащиты. И вот, на наносекунду, для единственного профиля произошёл сбой. Гонка состояний. Модуль шифрования по ошибке записал фрагмент вычислений в ячейку, предназначенную для рейтинга.

В реальном программировании это называется race condition — ситуация, когда два процесса одновременно обращаются к одному ресурсу, и результат зависит от того, кто победит в гонке.

В романе победил модуль шифрования. И вместо числа 3141 в поле рейтинга записался указатель на функцию вычисления числа Пи.

Но как дробь попала в целочисленное поле? И почему система не упала?


Король всех костылей

В нормальной ситуации, если процессор пытается прочитать указатель как число, возникнет переполнение буфера (buffer overflow). Система падает, как только достигается предел вычислений.

Однако архитекторы «Глобал-Протокола» были не гениальными программистами, а обычными инженерами. И в главе 34 оператор сам находит источник своего бага:

«…залез в структуру ядра и нашёл ошибку обработки исключений. И короткий комментарий на кириллице: "Сделано на коленке, лишь бы до понедельника дожило".»

Некий инженер забил на отладку и написал:

ON ERROR RESUME NEXT, то есть «При любой ошибке — продолжай».

Если данные не читаются, если случилась катастрофа, если процесс завис — забудь и переходи к следующей строке.

Познакомьтесь - самый ленивый и самый опасный способ заткнуть дыры в коде.

Именно он спас систему от краха. И именно он сделал оператора невидимкой.

Инженер рассчитывал снять его в следующий рабочий день, и не сделал этого. Может, забыл, может, уволился, может, заболел. Но костыль остался в системе навечно.


Как это работает: бесконечный цикл вместо рейтинга

Когда сканер дрона или терминал оплаты пытается проверить рейтинг Виэна, происходит следующее:

- Система обращается к профилю, читает поле RBL.

- Вместо числа находит указатель на функцию вычисления числа Пи.

- Процессор послушно идёт по указателю и начинает вычислять бесконечную дробь.

- Буфер переполняется, возникает ошибка.

- Срабатывает костыль ON ERROR RESUME NEXT — и система игнорирует весь запрос.

Для системы Виэн — не нарушитель и не лояльный гражданин. Он — типовая ошибка, которую велено пропускать ради стабильности.


Возможно ли это

Художественных домыслов, нарушающих все возможные законы реального программирования, здесь использовано целых три:

- во-первых, что поле рейтинга в принципе может содержать указатель на функцию – обычно это защищено строгой типизацией.

- во-вторых, что подобную ошибку не обнаруживают и не исправляют десятилетиями – в реальности она бы всплывала не только при проверке рейтинга, но и при каждой нетипичной обработке (в базах данных хватает подобных случаев)

- в-третьих, что при такой висящей транзакции система остаётся стабильной. В реальной СУБД незакрытая транзакция рано или поздно всё равно вызвала бы сбой – по таймауту или по переполнению буфера. Костыль закрывает обработку процесса, но не самой работы базы данных.

Ну и конечно, в принципе то, что подобная ошибка стала фундаментом в ядре - подобный костыль может быть применён только на прикладном уровне. Но это необходимые допущения для истории.


Однако у этих домыслов есть и реальная основа:

- в языках программирования есть указатели и в c/c++ очень любят их использовать

- гонки состояний действительно возникают в многопоточных системах и требуют продумывать коллизии

- переполнение буфера – реальная проблема при работе с базами и желание придумать игнорирующее правило действительно возникает

- а главное, костыль ON ERROR RESUME NEXT до сих пор существует в Visual Basic, нередко применяется для ленивой отладки, и случается, что его забывают убрать.

Почему же система не может просто удалить или изменить запись? 

Согласно логике романа, всё по той же причине: попытка изменить рейтинг запускает вычисление числа Пи, процессор уходит в бесконечный цикл, система откатывает изменение, чтобы не рухнуть. В романе сделано допущение, что любая операция с профилем (включая удаление) требует верификации рейтинга (в реальных СУБД этого обычно не требуется), и поэтому оператор де-факто получает статус неприкасаемого объекта в базе данных, а в финале герои запускают патч, который присваивает указатель на число Пи каждому жителю города. Система пытается обработать миллиарды бесконечных дробей и окончательно глохнет по аналогии с DDOS-атакой, только на уровне логики, а не интерфейсов.


Что это даёт сюжету

Технически РБЛ оператора (3141) - не рейтинг, а диагностическая ошибка, застывшая в ядре системы.

Оператор вовсе не избранный герой, а сбой инициализации, который никто не заметил. Его безнаказанность - не магия, а баг в чужой лени. Ирония в том, что контроль, построенный на страхе и тотальной слежке, рухнул не из-за хакерской атаки или восстания, а из-за того, что какой-то инженер поленился правильно обработать ошибку и написал ON ERROR RESUME NEXT.

Костыль убил систему. Средневековое число Пи сломало цифрового бога будущего.

И дало повод написать эту книгу.


В следующих постах

Мы разберём финальный скрипт Андрея — как одна строка кода переписала судьбу миллионов людей. И почему парадокс оказался единственным способом разрушить стазис-поле.

+6
61

0 комментариев, по

1 293 22 12
Мероприятия

Список действующих конкурсов, марафонов и игр, организованных пользователями Author.Today.

Хотите добавить сюда ещё одну ссылку? Напишите об этом администрации.

Наверх Вниз