Проблема в том, что в 64-битной системе указатели buffer и curr_pos могут лежать за пределами первых 4 гигабайт адресного пространства. В этом случае явное приведение указателей к типу UINT отбросит значащие биты, и работа алгоритма будет нарушена (см. рисунок 2).
Код плох, но это реальный код. Его задача состоит в поиске конца строки, обозначенного символом 0x0A. Код не будет работать со строками длиннее INT_MAX символов, так как переменная length имеет тип int. Однако нас интересует другая ошибка, поэтому будем считать, что программа работает с небольшим буфером и использование типа int корректно.
((UINT)curr_pos - (UINT)buffer < (UINT)length) );
while( (*(curr_pos++) != 0x0a) &&
Пример 2. Лишние приведения типов
Подобную ошибку может быть сложно выявить, если при этом портятся данные, используемые гораздо позднее.
Рисунок 1 Схематичное пояснение примера переполнения буфера
При переносе кода на 64-битную систему размер структуры Abcd увеличился и как следствие возникла ошибка переполнения буфера (см. рисунок 1).
В программе объявлены два объекта типа STRUCT_1 и STRUCT_2, которые перед началом использования необходимо очистить (инициализировать все поля нулями). Реализуя инициализацию, программист решил скопировать похожу строчку и заменил в ней "&Abcd" на "&Qwer". Но при этом он забыл заменить "sizeof(Abcd)" на "sizeof(Qwer)".По удачному стечению обстоятельств размер структур STRUCT_1 и STRUCT_2 совпадал в 32-битной системе и код корректно работал долгое время.
memset(&Qwer, 0, sizeof(Abcd));
memset(&Abcd, 0, sizeof(Abcd));
Пример 1. Переполнение буфера
Также вы можете познакомиться с демонстрационной версией инструмента , в состав которой входит статический анализатор кода Viva64, выявляющий практически все описанные в статье ошибки. Демонстрационная версия для скачивания.
Статья только демонстрирует различные виды 64-битных ошибок и не описывает методов их обнаружения и профилактики. Вы можете подробно познакомиться с методами диагностики и исправления дефектов в 64-битных программах, обратившись к следующим ресурсам:
Наша компания ООО "Системы программной верификации" занимается разработкой специализированного статического анализатора Viva64 выявляющего в коде приложений на языке Си/Си++. В ходе этой работы наша коллекция примеров 64-битных дефектов постоянно пополняется, и мы решили собрать в этой статье наиболее интересные на наш взгляд ошибки. В статье приводятся примеры как взятые непосредственно из кода реальных приложений, так и составленные синтетически на основе реального кода, так как в нем они слишком "растянуты".
Статья представляет собой наиболее полную коллекцию примеров 64-битных ошибок на языках Си и Си++. Статья ориентирована на разработчиков Windows-приложений, использующих Visual C++, но будет полезна и более широкой аудитории.
Коллекция примеров 64-битных ошибок в реальных программах
Коллекция примеров 64-битных ошибок в реальных программах
Статический анализатор кода для C/C++/C++11
Коллекция примеров 64-битных ошибок в реальных программах
Комментариев нет:
Отправить комментарий