Верите ли вы в волшебство? С логической точки зрения — конечно, нет! Программисты, разработчики — серьезные люди, с хорошим образованием и реалистичным взглядом на мир. Может вы и в детстве не любили сказки? Нет, я не буду больше отвечать за вас. Просто попрошу налить кружечку чая, почистить мандарин, взглянуть на снежинки за окном и только после этого начать читать эту Историю.

Перед вами рассказ о Злобном Баге. О том, как он неоднократно пытался испортить новогодние праздники. Часто ему удавалось воплотить свои коварные замыслы, но, к счастью, в каждой Сказке «злу» противостоит настоящее «добро».

Picture 3

Елочка-вирус


17 декабря 1987 года студент немецкого университета Клаустал-Зеллерфилд, будучи еще совсем молодым программистом, решил оригинально поздравить своих друзей. Он отправил всем близким и дорогим рождественскую ель! Конечно, он не срубил ее в лесу и даже не купил в магазине. Не забывайте, наш герой — программист, поэтому он написал программу на языке REXX для VM/CMS, которая после запуска выводила на экран милую елочку и теплые поздравления.

Рисунок 1 - Программа Christmas Tree - елочка вирус


Рисунок 1 — Программа Christmas Tree — елочка вирус

С благими намерениями и искренним желанием сделать добро писал код наш герой. Но Злобный Баг вклинился в процесс, произошла перегрузка сети и самовоспроизводящаяся программа Christmas на два дня парализовала работу частной почты IBM Vnet (цепочка: университетская сеть — EARN — BitNet — IBM-Vnet) по всему миру. Возникли сомнения: а не является ли герой — антигероем, а трогательное поздравление — вирусом? Доказать злой умысел автора программы Christmas Tree не удалось. Но без влияния Злобного Бага здесь точно не обошлось.

Аттракцион невиданной щедрости


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

Amazon — один из первых интернет-сервисов, на котором ежедневно продаются и покупаются десятки тысяч разнообразных товаров. Идеальное место для выбора подарков! Именно этим и занимались пользователи 12 декабря 2014 года. Особый ажиотаж вызвала потрясающая цена на тысячи товаров — всего 1 пенни (источник). Благодаря сервис за великолепный рождественский подарок, люди с особым энтузиазмом занялись покупками. А Злобный Баг ухмылялся в сторонке, ожидая реакции продавцов, еще не знающих о том, что они понесли огромные убытки.

Ошибка закралась в программное обеспечение RepricerExpress, отвечающее за синхронизацию цен в онлайн-магазинах. С его помощью продавцам проще конкурировать на рынке, оперативно реагируя на изменение цен аналогичных товаров.

Что сделал Злобный Баг? Он проник в RepricerExpress еще на этапе проектирования и тестирования, но не заявлял о себе до того момента, пока… Один из поставщиков, закрутившись в предпраздничной суете, случайно установил единую цену на весь свой ассортимент — 1 пенни. Программа приняла это значение за минимальное и снизила цену на товары других продавцов.

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

Рисунок 2 - Правильный интерфейс системы (появился столбец Your Minimum Price)


Рисунок 2 — Правильный интерфейс системы (появился столбец Your Minimum Price)

День, когда произошла данная ошибка, продавцы Amazon запомнят надолго. Они потеряли тысячи долларов, многие оказались на грани банкротства (источник). Если бы не оперативные меры Amazon, сумевшего аннулировать большую часть заказов, то репутация крупнейшего интернет-магазина была бы совершенно испорчена.

Разработчики RepricerExpress извинились за сбой ПО, опубликовав заявление в своем официальном блоге.

Apple против Нового года


Помните фильм "Гринч — похититель Рождества"? Видимо, Злобный баг вдохновился его сюжетом, решив нанести удар «яблочным» девайсам. В феврале 2016 года владельцы техники Apple обнаружили занятный баг. В социальных сетях зародилась легенда о том, что если установить дату 1 января 1970 года, а затем выполнить перезагрузку устройства, то произойдет полный крах системы, а вместо смартфона или планшета у вас в руках окажется кирпич с эмблемой «яблочко». При этом возможности откатить действие нет. Были сведения о присутствии данной ошибки на устройствах с 64-битным процессором: Apple A7, A8, A8X, A9 и A9X: iPhone 5S и последующие, iPad Air и iPad Mini 2 и новее, а также 6-е поколение iPod Touch. Версия операционной системы значения не имела.

Picture 2


Нашлись ли желающие опытным путем проверить наличие бага? Несомненно! По всему миру прокатилась волна убийств гаджетов Apple. К счастью, умельцы нашли способ вернуть работоспособность «кирпичам». В Apple официальную причину ошибки не озвучили, но заявили о возможности такого бага, при ручной установке на iOS-устройстве дату в мае 1970 года или ранее.

Пользователи провели собственное расследование. В результате сформировалась следующая версия: к ошибке могла привести переменная с отрицательным значением, хранящая в себе время в формате UNIX. Почему это могло произойти?

Вариант 1. По причине того, что время представлено в UNIX-формате, начало отсчета ведется с 1 января 1970 года, т.е. является нулем. При изменении часового пояса, переменная может принять значение меньше нуля.

Вариант 2. Баг характерен для 64-х битных устройств, поэтому возможно, в первую очередь вычисляется 32-х битная метка времени, затем происходит смещение по часовому поясу, метка конвертируется в размер указателя, по этой причине старшие биты заполняются неверно и… Добро пожаловать в XXII век!

Сон от IPhone


Продолжительный сон, не прерываемый звуком будильника, — разве это не мечта большинства из нас? iPhone — не Газпром, но исполняет мечты своих пользователей! Все те, кто хотел бодро начать новый 2013 год и поставил будильник на 1 января, благополучно проспали. Злобный баг явно замыслил ввести огромное количество пользователей в режим «спящей царевны», т.к. вплоть до 3 января будильник на iPhone не работал.

Picture 7


Apple снова решил отмолчаться. Но версия о причинах возникновения ошибки все равно распространилась. Для отображения года используется стандарт ISO week date, он широко применяется в финансовых организациях для удобства формирования отчетного (финансового) года. Его особенность состоит в том, что новый год считается новым только с той недели, которая содержит первый четверг года. Календарь в стандарте ISO week date содержит 52 или 53 недели (364 или 371 день). Таким образом, iPhone жил по старому году, а новый 2013 наступил только 7 января — с новой полной недели года.

Была и альтернативная версия, в которой в качестве Злобного бага выступал сам Стив Джобс. Якобы, основатель Apple любил спать, вот и придумал такую фичу. Конечно, это шутка. А вот последствия у такого, казалось бы, несерьезного бага оказались более чем неприятными: люди проспали работу, потеряли деньги, опоздали на важные встречи (Источник).

Полет отменяется


Цена ошибки в программном обеспечении — фактор, который разработчики никогда не должны игнорировать. Доказательство — в следующей предновогодней истории о баге.

12 декабря 2014 года в британском центре УВД Национальной службы воздушного движения Великобритании (NATS) произошел программный сбой. Работа части аэропортов, в том числе таких загруженных гигантов, как Хитроу, Гатвик, Станстед, Бирмингем, Кардифф и Глазго была остановлена. Усугубило проблему и время, которое Злобный баг выбрал для атаки — пятница, вторая половина дня, преддверие рождественских праздников.

Сбой длился чуть более получаса — 36 минут, но его последствия свидетельствуют о крайне высокой цене ошибки. Злобный баг постарался на славу:

  • 92 рейса отменено
  • 170 рейсов задержано
  • 10 воздушных суден были вынуждены уйти на запасные аэродромы
  • 125000 пассажирам были причинены неудобства
  • 623 млн фунтов стерлингов потеряла британская казна

Подобная ситуация не могла остаться без внимания. Было проведено расследование. Управление гражданской авиации (CAA) и NATS в заключительном отчете описывают баг в программном обеспечении System Flight Server (SFS). Этот сервер отвечает за то, чтобы в систему управления NATS в режиме реального времени поступали данные на контроллер рабочих станций. В системе существует два одинаковых SFS — работающий и запасной. Оба вычисляют одни и те же данные. При отключении основного SFS, в работу вступает запасной. Система работала при аппаратных сбоях, но по каким-то причинам ни на одном из серверов не была предусмотрена защита от программных исключений.

Максимальное количество одновременно функционирующих рабочих станций (мест управления полетами и наблюдения за ними) — 193. Теоретически. Фактически же в коде SFS прописано совершенно другое значение — 151. Поэтому, когда произошла попытка одновременного подключения 153 рабочих станций, началась перезагрузка и последующее «падение» системы. Позже выяснилось, что «скрытая неисправность программного обеспечения» была допущена еще в 1990 году. Удивительно, что она не проявилась раньше.

Проблема 2000 и 2038


2000 год был одним из самых ожидаемых. Смена тысячелетия, по мнению ряда экспертов самых разных областей, непременно должна сопровождаться Концом света или, что не менее страшно — восстанием машин.

Чем же аргументировался страх перед Терминаторами? Логикой! Первые компьютеры были медлительны, поэтому, чтобы не тратить столь ценную производительность на пустяки, разработчики приняли решение использовать два знака представления кода в датах. Например, 23 марта 1991 года выглядело как 23.03.91. Визуально такое обозначение не «режет глаз», данный вариант записи даты кажется абсолютно привычным. Но с точки зрения компьютера все не так просто: 2000 год и 1900 получают одинаковое обозначение: 00. Таким образом, при наступлении 2000 года внутренние часы компьютера переведутся на 1900 год.

Последствия подобного сбоя представлялись крайне ужасными: выход из строя программ, самопроизвольный запуск ракет, обрушение финансового рынка. А самые страшные события должны были произойти в России, как в стране, наименее готовой к новому летоисчислению.

Но совсем скоро наступит уже 2017 год, а значит, Конец света не произошел.

Впрочем, некоторые сбои при смене тысячелетия все же произошли:

  • Пострадали компьютерные сети British Telecom. Их работала была парализована, а для восстановления потребовалось проанализировать около миллиона строк кода. Обошлось это British Telecom недешево — около $0.5 млрд.
  • В Испании были зафиксированы происшествия на 9 ядерных реакторах. К счастью, обошлось без последствий.
  • В Монголии «Проблема 2000» затронула систему начала движения поездок и билетные кассы.

Некоторые баги были весьма забавны:

  • Сроки заключения в одной из испанских тюрем выросли/сократились на 100 лет
  • В некоторых магазинах Греции люди при покупке получили чек, датированный 1900 годом
  • В южнокорейском госпитале компьютерная программа «Контроль за пациентами» объявила годовалого ребенка 99-летним стариком
  • А жители небольшого города в США получили просроченные на 100 лет счета за пользование электроэнергией

Проблема 2000 — это яркий пример того, как СМИ способны воздействовать на человечество. Следующей волны паники по аналогичному поводу стоит ожидать в 2038 году. 19 января 2038 года в 03:14:07 по Гринвичу компьютеры и другие устройства с 32-битной системой не смогут больше верно отсчитывать время. Многие вычислительные устройства отсчитывают системное время с 1 января 1970 года в секундах, используя 32-битное значение, а секунда хранятся в виде signed int (32-битного целого со знаком). В 2038 году наступит 2 147 483 648-я секунда, которую просто не будет возможности записать системой, и тогда счётчик примет отрицательное значение.

Как предотвратить системную ошибку? Заменить все 32-битные процессоры на 64-битные.

Как помочь Добру?


По традиции, Добро побеждает Зло, но борьба не прекращается ни на миг. Можно ли истребить всех Злобных багов? Скорее всего, нет, но вполне реально сделать так, чтобы их армия понесла значительный урон. Для этого программисты, сражающиеся за Добро, т.е. качественный код, должны ответственно подойти к выбору вспомогательных средств. Вооружайтесь статическим анализатором PVS-Studio! А также вы можете посмотреть хоррор-короткометражку о том, как Единорог PVS-Studio спасает Пингвина Linux от Злобного бага.

Вдохновились? Тогда предлагаем всем разработчикам помочь Добру! Команда PVS-Studio уже сделала значительный шаг в этом направлении, предложив бесплатную версию анализатора.

Picture 6


Уважаемые программисты, желаем вам удачи в Новом году и пусть ваши истории о Злобных багах всегда заканчиваются победой Добра!
Поделиться с друзьями
-->

Комментарии (16)


  1. DrZlodberg
    23.12.2016 15:10
    +3

    Как предотвратить системную ошибку? Заменить все 32-битные процессоры на 64-битные.

    А при чём тут процессор? 64-битный так же обнулит старшие если само значение 32-битное. А 32 вполне корректно отработает 64 если программа об этом в курсе.


    1. webkumo
      23.12.2016 16:05

      Вот и я удивился — вроде в PVS Studio должны работать грамотные люди… а такой ляп допустили...


    1. Lure_of_Chaos
      23.12.2016 18:08
      +1

      Как дурно на Вас Java (или что там кроссплатформенное?) влияет. Ничего, что размер целого зависит от платформы?
      т.е. надо заменить и процессор, и программы для 64 архитектуры использовать.


      1. DrZlodberg
        23.12.2016 18:29
        +1

        Внезапно… А ничего, что когда имеешь дело с общими и достаточно специфичными данными обычно используешь переменные необходимого для работы с ними размера. Не «кросплатформенные», а именно конкретные. Иначе они у вас просто в структуру не влезут. Т.е. будь у нас хоть 128-битный проц — всё равно в структуру больше чем 32 бита не влезет, увы. Это сейчас всё в тестовые форматы сериализуют, там пофиг на размер. А так уж повелось, что много где до сих пор используется именно 32бит unnix time представление. (зачем там используется знаковое — отдельный вопрос). В программе вы можете считать в каком удобно размере, но вернуть системе не получится.

        Ну и, помнится под досом на древних XT никаких проблем с работой с 32-битными переменными не было (ну разве что приходилось считать по частям). 64 при острой необходимости тоже считали, просто делили на 4 куска вместо 2х.


      1. mapron
        24.12.2016 09:43

        Ерунду говорите, базы данных давно работают с 64-битными метками и 128-битными значениями даже на 32-битных архитектурах. Ну и что, что значение за один так не посчитается.


    1. vsespb
      24.12.2016 12:34

      То-то есть куча багов со временем, которая только на 32битных платформах…


      1. DrZlodberg
        24.12.2016 13:52

        Например? Сходу могу вспомнить и более старые. Например компактное раздельное(отдельно часы, минуты, секунды) хранение времени в FAT (если мне не изменяет память) позволяло установить в метке времени более чем 59 минут или секунд. Чем активно пользовались разные вирусы в качестве метки заражения.


        1. vsespb
          24.12.2016 14:04

          Моя очередь.
          https://bugzilla.redhat.com/show_bug.cgi?id=1057047#c5

          Проблемы с функциями времени, при этом «so I cannot back-port the perl changes to support 32-bit platforms.» и указаны типы данных на 32 битных и 64 битных платформах. Они отличаются. Так что «Заменить все 32-битные процессоры на 64-битные» (это то что в треде, что мы обсуждаем) вполне себе годный совет.


          1. webkumo
            24.12.2016 14:21

            Возможно на 64-битных системах работа со временем более удобна и выше вероятность не набагать, но это не означает, что решением является переход на 64-битные системы. Такой шаг всего-лишь позволит упростить кодовую базу… что для работы со временем, безусловно, полезно… но всё же не необходимо.


            1. vsespb
              24.12.2016 14:35

              Полезно, необходимо… Это практический совет.


            1. DrZlodberg
              24.12.2016 14:55
              -1

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


              1. webkumo
                24.12.2016 20:15

                Размер выбирался исходя из кучи параметров, в том числе производительности систем того времени и удобства работы с такими данными… На тот момент — это был оправданный шаг, сейчас мы вынуждены думать о том, как это легаси обойти...


                1. DrZlodberg
                  24.12.2016 20:25

                  В основном исходя из размера и того,. что 640кб...
                  Производительность на счётчике секунд несущественна даже на машинах того времени, с удобством никаких проблем тоже нет.
                  На асм вместо add используем call add64 какой-нибудь, на С компилятор сам вполне способен подставить нужное. Арифметика с плавающей точкой так и работала (сопроцессоры тогда ещё не были мейнстримом). В зависимости от флагов или собирал нативный код или подменял на соответствующие вызовы эмулятора.
                  Ну и изначально речь была не об этом, а о том, что собственно разрядность процессора тут вообще никаким боком.


          1. DrZlodberg
            24.12.2016 14:53
            +1

            Тот факт, что они отличаются имеет мало отношения к типу процессора. Использование переменных недостаточной или платформозависимой размерности — проблема исключительно кривизны рук автора.
            И тот факт, что для починки иногда достаточно перекомпиляции на другой платформе этого факта не отменяет совершенно. Тем более что на другой платформе всё точно так же внезапно и без предупреждения может сломаться. А ещё есть системные переменные, которые имеют размерность жестко заданную системой. И никакой процессор вас не спасёт если система понимает только 32-бит формат.
            И да, повторюсь. Ни что не мешает использовать 64-битные переменные на 32-бит платформе. Ну вот вообще ни что. Кроме упомянутого выше фактора.


    1. Nekto_Habr
      25.12.2016 22:13

      Почитал всю эту ветку комментов (14 на момент ответа). Объясните непрограммисту, почему время — это так сложно для всемогущих компьютеров?


      1. DrZlodberg
        25.12.2016 23:09

        Ну вообще время — довольно хитрый предмет и проблем с ним хватает. Тут была статься (вроде даже не одна) но не смог найти.
        Однако в контексте данного треда сложность только одна. Исторически сложившийся общепринятый формат хранения времени, размерности которого скоро станет недостаточно для корректной работы. И именно хранения, (и обмена соответственно) а не расчёта. Собственно в статье есть пример аналогичной проблемы «2000 года», когда хранение только 2х цифр года вызвало ошибки при переполнении.
        Ну и как обычно в таких ситуациях — проблема со старым софтом, который не в курсе, что счётчик надо бы расширить.