Короче говоря: это не просто проблема программирования, это более сложная проблема
Дефект в Ariane 5 не был вызван ни одной причиной.На протяжении всего процесса разработки и тестирования было много этапов, на которых этот дефект мог быть выявлен.
• Программный модуль был повторно использован в новой среде, где условия работы отличались от требований к программному модулю.Эти требования не были пересмотрены.
• Система обнаружила и распознала ошибку.К сожалению, спецификация механизма обработки ошибок была непоследовательной и привела к окончательному уничтожению.
• Ошибочный модуль никогда не был должным образом протестирован в новой среде - ни на уровне оборудования, ни на уровне системной интеграции.Поэтому ошибка разработки и реализации не была обнаружена.
См. Diff с правильным кодом:
--- LIRE_DERIVE.ads 000 Tue Jun 04 12:00:00 1996
+++ LIRE_DERIVE.ads Fri Jan 29 13:50:00 2010
@@ -3,10 +3,17 @@
if L_M_BV_32 > 32767 then
P_M_DERIVE(T_ALG.E_BV) := 16#7FFF#;
elsif L_M_BV_32 < -32768 then
P_M_DERIVE(T_ALG.E_BV) := 16#8000#;
else
P_M_DERIVE(T_ALG.E_BV) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BV_32));
end if;
-P_M_DERIVE(T_ALG.E_BH) :=
- UC_16S_EN_16NS (TDB.T_ENTIER_16S ((1.0/C_M_LSB_BH) * G_M_INFO_DERIVE(T_ALG.E_BH)));
+L_M_BH_32 := TBD.T_ENTIER_32S ((1.0/C_M_LSB_BH) * G_M_INFO_DERIVE(T_ALG.E_BH));
+
+if L_M_BH_32 > 32767 then
+ P_M_DERIVE(T_ALG.E_BH) := 16#7FFF#;
+elsif L_M_BH_32 < -32768 then
+ P_M_DERIVE(T_ALG.E_BH) := 16#8000#;
+else
+ P_M_DERIVE(T_ALG.E_BH) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BH_32));
+end if;
Более подробная информация:
A) The “Ошибка операнда »произошла из-за неожиданно большого значения ЧД (горизонтального смещения), рассчитанного внутренней функцией на основе значения« горизонтальной скорости », измеренного датчиками на платформе.
Значение ЧД служило индикатором точности позиционирования Платформы.значение ЧД оказалось намного больше, чем ожидалось, поскольку траектория полета Ariane 5 на ранней стадии значительно отличалась от траектории полета Ariane 4 (где этот программный модуль использовался ранее), что привело к значительно более высокой «горизонтальной скорости».».
Последним действием, имевшим фатальные последствия, было прекращение работы процессора.Соответственно вся навигационная система перестала функционировать.Было технически невозможно возобновить ее действия.
B) Однако Ariane 5, в отличие от предыдущей модели, обладал принципиально иной дисциплиной для выполнения предполетных действий - настолько отличающейся, что работа рокового программного модуля после времени запуска вообще не имела смысла,Однако модуль был повторно использован без каких-либо изменений.
Исследование показало, что в этом программном модуле было задействовано до семи переменных.Оказалось, что разработчики провели анализ всех операций, которые потенциально могли бы сгенерировать исключение для уязвимости.
Это было их очень сознательное решение добавить надлежащую защиту к четырем переменным и оставить три - включая ЧД - незащищенными.Причиной этого решения стало убеждение, что для этих трех переменных возникновение ситуации переполнения в принципе невозможно.
Эта достоверность была подтверждена расчетами, показывающими, что ожидаемый диапазон физических параметров полета, на основании которых определяются значения этих переменных, таков, что не может привести к нежелательной ситуации.И это было правдой - но для траектории, рассчитанной для модели Ariane 4.
И ракета нового поколения Ariane 5 была запущена по совершенно другой траектории, для которой оценки не проводились.Между тем, оно (вместе с высоким начальным ускорением) было таким, что «горизонтальная скорость» превышала расчетную (для Ariane 4) более чем в пять раз.
Защита для всех семи (включая BH) переменных не была предоставлена, поскольку для компьютера IRS была объявлена максимальная рабочая нагрузка в 80%.Разработчики должны были искать способы уменьшить ненужные вычислительные затраты, и они ослабили защиту, где теоретически нежелательная ситуация не могла возникнуть.Когда он возник, такой механизм обработки исключений вступил в действие, который оказался совершенно неадекватным.
Этот механизм включал следующие три основных действия.
• Информация о возникновении чрезвычайной ситуации должна передаваться черезшина к бортовому компьютеру OBC.
• Параллельно она - вместе со всем контекстом - записывалась в перепрограммируемую память EEPROM (которую в ходе исследования можно было восстановить и прочитать ее содержимое).
• Процессор IRS должен был выйти из строя.
Последнее действие оказалось фатальным - именно он произошел в ситуации, которая на самом деле была нормальной (несмотря на исключение программного обеспечения, созданное из-за незащищенного переполнения), что привело к катастрофе.
C) Скорость была представлена в виде 64-разрядного числа с плавающей запятой.Преобразование в 16-разрядное целое число со знаком вызвало переполнение. Текущая скорость Ariane 5 была слишком высока, чтобы представить ее как 16-разрядное целое число. Обработка ошибок была исключена из соображений производительности
(защита для всех семи (включаяПеременные не были предоставлены, поскольку для компьютера IRS была объявлена максимальная рабочая нагрузка в 80%. Разработчикам пришлось искать способы уменьшить ненужные вычислительные затраты, и они ослабили защиту там, где теоретически нежелательная ситуация не могла возникнуть.)
Согласно презентации Жан-Жака Леви (1049 * 1 , 2 ) (которая была частью команды, которая искала источник проблемы), фактический исходный код в Аде, которыйпричиной проблемы было следующее .:
-- Vertical velocity bias as measured by sensor
L_M_BV_32 := TBD.T_ENTIER_32S ((1.0/C_M_LSB_BV) * G_M_INFO_DERIVE(T_ALG.E_BV));
-- Check, if measured vertical velocity bias ban be
-- converted to a 16 bit int. If so, then convert
if L_M_BV_32 > 32767 then
P_M_DERIVE(T_ALG.E_BV) := 16#7FFF#;
elsif L_M_BV_32 < -32768 then
P_M_DERIVE(T_ALG.E_BV) := 16#8000#;
else
P_M_DERIVE(T_ALG.E_BV) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BV_32));
end if;
-- Horizontal velocity bias as measured by sensor -- is converted to a 16 bit int without checking P_M_DERIVE
P_M_DERIVE(T_ALG.E_BH) := UC_16S_EN_16NS (TDB.T_ENTIER_16S ((1.0/C_M_LSB_BH) * G_M_INFO_DERIVE(T_ALG.E_BH)));
Последняя строка (показанная здесь в виде двух строк текста) вызвала переполнение, при котором преобразование из 64 битов в 16 битов без знака не защищено.Предыдущий код защищен тестированием перед присвоением, если число слишком велико.
Правильный код был бы:
L_M_BV_32 := TBD.T_ENTIER_32S ((1.0/C_M_LSB_BV) * G_M_INFO_DERIVE(T_ALG.E_BV));
if L_M_BV_32 > 32767 then
P_M_DERIVE(T_ALG.E_BV) := 16#7FFF#;
elsif L_M_BV_32 < -32768 then
P_M_DERIVE(T_ALG.E_BV) := 16#8000#;
else
P_M_DERIVE(T_ALG.E_BV) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BV_32));
end if;
L_M_BH_32 := TBD.T_ENTIER_32S ((1.0/C_M_LSB_BH) * G_M_INFO_DERIVE(T_ALG.E_BH));
if L_M_BH_32 > 32767 then
P_M_DERIVE(T_ALG.E_BH) := 16#7FFF#;
elsif L_M_BH_32 < -32768 then
P_M_DERIVE(T_ALG.E_BH) := 16#8000#;
else
P_M_DERIVE(T_ALG.E_BH) := UC_16S_EN_16NS(TDB.T_ENTIER_16S(L_M_BH_32));
end if;
Другими словами, такая же проверка переполнения должна была присутствовать для горизонтальной части расчета (E_BH), как уже присутствовала длявертикальная часть расчета (E_BV).
'Источник: http://moscova.inria.fr/~levy/talks/10enslongo/enslongo.pdf
(По 2019-01-24 можно найти по адресу: http://para.inria.fr/~levy/talks/10enslongo/enslongo.pdf)
https://habr.com/ru/company/pvs-studio/blog/306748/
https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%9F%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3