The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



"Анализ зависимости безопасности кода от используемого языка программирования"
Версия для распечатки Пред. тема | След. тема
Форум Разговоры, обсуждение новостей
Исходное сообщение [ Отслеживать ]
Подсказка: Для контроля за появлением новых сообщений - перед выходом жмите "Пометить прочитанным".
. "Анализ зависимости безопасности кода от используемого языка ..." +/
Сообщение от Ordu (ok), 23-Дек-20, 03:36 
> Смешное заявление: программа работает, но... не работает. При чём заметьте на том же железе

Да. Если взять компилятор из 80-х, будет работать. Если отключить оптимизации в современном компиляторе, будет работать. Если же современный компилятор и с оптимизациями, то работать не будет.

> То, что программа у вас в результате "работает предсказуемо", поскольку вы может быть способны как-то предсказать, как она будет работать, вовсе не значит определённого поведения. Ваши способности к предсказанию и определение поведения программы - вещи весьма разные.

Он дело советует -- сходи и почитай статьи, которые он рекомендует. Вот сходи и почитай, и если останется желание позубоскалить, то зубоскаль. Но сначала почитай.

В том-то и проблема, что предсказать поведение программы теперь невозможно, не учитывая всех тех UB описанных в стандарте, как UB.

Взять, скажем, целочисленное переполнение. В C -- это UB. Которое исторически трактовалось как "сделать то, что процессор делает при сложении целых". То есть, сложение в C было таким сложением, как его понимает CPU. Программисты на это полагались и C был задуман именно таким, чтобы программисты на это полагались: C был высокоуровневым ассемблером. Вдумайся в это: C был сделан именно таким с глубокой инженерной мыслью, предоставить программисту возможность писать "высокоуровневый" код, пользуясь при этом низкоуровневыми операциями, дать возможность программисту оставаться настолько близко к железу, насколько это возможно.

То есть, исходный C предполагал, что программист обладает этой "способностью к предсказанию" поведения кода с UB, на которую ты тут зубоскалишь. Знание программистом архитектуры даёт ему чёткое понимание того, что произойдёт при разадресации NULL. Или что произойдёт при переполнении целого.

Потом пришли современные техники оптимизации кода, которые выполняют оптимизацию многими фазами, и хоть каждая фаза вполне разумна, но в процессе трансформаций кода может теряться смысл выполняемых программой телодвижений, и затем вдруг -- хоп -- и UB становится русской рулеткой: что сделает отоптимизированная программа уже не угадать. Вплоть до дурацких ситуаций, когда UB спрятанный в if(condition) { here_UB(); }, присобачивает программе UB даже при !condition. (Хотя, вроде, такие вещи даже современные компиляторы C считают зашкваром).

Таким образом, C перестал быть высокоуровневым ассемблером. Он превратился в минное поле с разложенными по нему граблями. Теперь сложение С -- это не сложение CPU. На подавляющем большинстве машин целые числа хранятся в дополнительном коде (я, честно говоря, даже не знаю никаких современных процессоров, которые бы делали иначе). Но если я хочу использовать переполнение в своих целях -- например мне как раз нужна арифметика в кольце вычетов по модулю степени двойки, и мне пофигу что там случается с битами, которые вылетают за пределы диапазона, которые поддерживает int, мне главное чтобы достаточное количество младших бит сохранилось бы, -- то я не могу это писать на C. Мне придётся подключать ассемблер для таких вещей. Кстати, я давненько не читывал стандарт на C: они там не запилили в стандарт функций, для того, чтобы работать с переполнением без UB? Что-нибудь типа overflowing_add? Ведь куча крипты работает в кольцах по модулю степени двойки, им бы вовсе не помешало такое дополнение к стандарту.

То есть, современный C переопределил понятие UB, нагрузил его новой семантикой. Если раньше UB было чем-то таким, что неопределено ровно до тех пор, пока мы не определились с архитектурой, под которую пишем программу, а дальше оно чётко определено и предсказуемо, то теперь UB -- это карт-бланш компилятору на выполнение абсолютно любых преобразований кода. Теперь UB остаётся UB всегда, переполнение целого может запустить какой-нибудь builtin компилятора, взрывающий процессор, и типа так и надо, типа "ну а чё вы хотели, у вас же UB отклеился".

Ответить | Правка | Наверх | Cообщить модератору

Оглавление
Анализ зависимости безопасности кода от используемого языка программирования, opennews, 20-Дек-20, 18:53  [смотреть все]
Форумы | Темы | Пред. тема | След. тема



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру