Комментарии 5
Для варианта «Windows MSVC 2019 16.5.4, усложнённый пример, /O1, /O2» первого примера логика работы описана неправильно.
Нет. Там же не mov, а cmove — условное копирование, если ZF=1. Поэтому вывод
неверен. В stream выводится 1, если rand() вернул 0, а в противном случае выводится младший байт значения EBX, установленного в строке 6 командой «movzx ebx,byte ptr [rsp+30h]» — т.е. первый байт стека над адресом возврата.
— копирует это же значение в ebx (строка 11);
Нет. Там же не mov, а cmove — условное копирование, если ZF=1. Поэтому вывод
В stream выводится единица.
неверен. В stream выводится 1, если rand() вернул 0, а в противном случае выводится младший байт значения EBX, установленного в строке 6 командой «movzx ebx,byte ptr [rsp+30h]» — т.е. первый байт стека над адресом возврата.
0
Интересный анализ, практически небольшой детектив. Озвучу пару заметок:
- Как видно из примеров (фактически, это наброски и демонстрации простых эксплоитов), данное UB вполне может использоваться в качестве потенциальной уязвимости в составной атаке.
- Даже на высоких уровнях предупреждений и с максимальным количеством включенных флагов-warning'ов компиляторы не всегда способны определить наличие ошибочного пути выполнения, на котором не происходит возврата значения (и предупредить программиста). Особенно легко получить такую ситуацию в сложном шаблонном коде: буквально неделю назад пришлось 2 часа дебажить с gdb превращение памяти в неотлаживаемое месиво из за тупого пропуска слова
return
в функции-однострочнике.
+3
Странно. Почему оптимизирующий компилятор не превратил код
bool bad()
{
if (rand() == 0) {
return true;
}
}
в
bool bad()
{
rand();
return true;
}
Функция rand() имеет побочный эффект, поэтому выбросить её вызов нельзя, а вот возврат true — это разрешённый стандартом вариант неопределённого поведения. И результирующий код короче, и известное возвращаемое значение позволяет дальнейшую оптимизацию.
bool bad()
{
if (rand() == 0) {
return true;
}
}
в
bool bad()
{
rand();
return true;
}
Функция rand() имеет побочный эффект, поэтому выбросить её вызов нельзя, а вот возврат true — это разрешённый стандартом вариант неопределённого поведения. И результирующий код короче, и известное возвращаемое значение позволяет дальнейшую оптимизацию.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Исследование одного неопределённого поведения