Статический анализ Си++ кода Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации» E-mail: karpov@viva64.comkarpov@viva64.com.

Презентация:



Advertisements
Похожие презентации
PVS-Studio, решение для разработки современных ресурсоемких приложений ООО «Си ПроВер» («Системы программной верификации»)
Advertisements

Проблема переноса приложений на 64-битные платформы Процесс миграции кода неизбежен. Миграция C/C++ приложений.
Статический анализ кода: современный взгляд Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации»
ПРОГРАММИРОВАНИЕ/ ЯЗЫКИ ПРОГРАММИРОВАНИЯ Лекция 4 Работа с бинарными файлами (весенний семестр 2012 г.) Доцент Кафедры вычислительных систем, к.т.н. Поляков.
Д.з Язык С++ - занятие 31. Задача 1: 1/1 + 1/3 + 1/5 … #include using namespace std; int main() { int n; cin >> n; double sum = 0;// Сумма for.
ЕГЭ информатика Алгоритмизация и программирование Консультация 3.
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Учебный курс Объектно-ориентированный анализ и программирование Лекция 4 Трансформация логической модели в программный код Лекции читает кандидат технических.
Лекция 1. Введение Красс Александр СПбГУ ИТМО, 2008.
Функции Функция – именованная последовательность описаний и операторов, выполняющая некоторое действие. Может иметь параметры и возвращать значение. Функция.
Язык JavaScript Скриптовый язык для выполнения на html-страницах.
ООП Классы Данные отдельно, методы отдельно struct Node { Node* next; void* data; }; struct List { Node* first; int size; }; void* allocate() { … } void.
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
Краткое введение в язык программирования С Аксёнов Сергей Владимирович к.т.н., доцент каф.ОСУ ТПУ Томский политехнический университет.
ЕГЭ 2011 Информатика и ИКТ Консультация 3 18 марта.
Обработка исключительных ситуаций Исключительная ситуация (исключение) – это ошибка, возникающая во время выполнения программы. Например, ошибка работы.
Электронный задачник по программированию для системы 1С:Предприятие М. Э. Абрамян, М. Ю. Беренкеева Южный федеральный университет, факультет математики,
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
OpenGL и Direct3D сравнение стандартов Выполнил: Пенкин А. Группа И-204.
Практическое программирование на Java к.ф.-м.н. Козлов Дмитрий Дмитриевич Кафедра АСВК, Лаборатория Вычислительных комплексов.
Транксрипт:

Статический анализ Си++ кода Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации»

О чем доклад Мы все допускаем ошибки при программировании и тратим массу времени на их устранение. Один из методов который позволяет быстро диагностировать дефекты – статический анализ исходного кода.

«Надо сразу писать хороший код» - не работает на практике! даже лучшие программисты ошибаются и делают опечатки; далее - ряд примеров ошибок, обнаруженных статическим анализатором кода в известных проектах; для анализа использовался инструмент PVS-Studio.

Приоритет операций & и ! Return to Castle Wolfenstein - компьютерная игра, шутер от первого лица, разработанный компанией id Software. Движок игры распространяется по GPL лицензии. #define SVF_CASTAI 0x if ( !ent->r.svFlags & SVF_CASTAI ) if ( ! (ent->r.svFlags & SVF_CASTAI) )

Использование && вместо & #define REO_INPLACEACTIVE (0x L) #define REO_OPEN (0x L) if (reObj.dwFlags && REO_INPLACEACTIVE) m_pRichEditOle->InPlaceDeactivate(); if(reObj.dwFlags && REO_OPEN) hr = reObj.poleobj->Close(OLECLOSE_NOSAVE); Stickies - желтые клеящиеся бумажки, только на мониторе.

Undefined behavior while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') { Miranda IM (Miranda Instant Messenger) - программа мгновенного обмена сообщениями для Microsoft Windows.

Использование delete для массива auto_ptr child_array(new VARIANT[child_count]); ~auto_ptr() { delete _Myptr; } Chromium - веб-браузер с открытым исходным кодом, разработанный компанией Google. На основе Chromium создаётся браузер Google Chrome. Использовать auto_ptr для массивов нельзя. В деструкторе auto_ptr уничтожается только один элемент: В качестве альтернативы, например, можно использовать boost::scoped_array.

Всегда истинное условие WinDjView - быстрая и компактная программа для просмотра файлов формата DjVu. inline bool IsValidChar(int c) { return c == 0x9 || 0xA || c == 0xD || c >= 0x20 && c = 0xE000 && c = 0x10000 && c

Оформление кода отличается от его логики if(pushval != 0) if(pushval) v->GetUp(-1) = t; else v->Pop(1); Squirrel - интерпретируемый язык программирования, разработанный специально для использования в качестве скриптового языка в приложениях реального времени, таких как компьютерные игры. v->Pop(1); - никогда не вызывается

Случайное объявление локальной переменной FCE Ultra – открытый эмулятор приставки Nintendo Entertainment System int iNesSaveAs(char* name) {... fp = fopen(name,"wb"); int x = 0; if (!fp) int x = 1;... }

Работа с char как с unsigned char // check each line for illegal utf8 sequences. // If one is found, we treat the file as ASCII, // otherwise we assume an UTF8 file. char * utf8CheckBuf = lineptr; while ((bUTF8)&&(*utf8CheckBuf)) { if ((*utf8CheckBuf == 0xC0)|| (*utf8CheckBuf == 0xC1)|| (*utf8CheckBuf >= 0xF5)) { bUTF8 = false; break; } TortoiseSVN клиент для системы контроля версий Subversion, выполненный как расширение оболочки Windows.

Случайные восьмеричные числа oCell._luminance = uint16(0.2220f*iPixel._red f*iPixel._blue f*iPixel._green);.... oCell._luminance = 2220*iPixel._red *iPixel._blue *iPixel._green; eLynx Image Processing SDK and Lab

Одна переменная для двух циклов static int i,j,k,l,m;... for(j=0; j

Выход за границы массива #define SBMAX_l 22 int l[1+SBMAX_l]; for (r0 = 0; r0 < 16; r0++) {... for (r1 = 0; r1 < 8; r1++) { int a2 = gfc->scalefac_band.l[r0 + r1 + 2]; LAME - свободное приложение для кодирования аудио в формат MP3.

Приоритет операций * и ++ STDMETHODIMP CCustomAutoComplete::Next(..., ULONG *pceltFetched) {... if (pceltFetched != NULL) *pceltFetched++;... } (*pceltFetched)++; eMule - это клиент для сети обмена файлами ED2K.

Ошибка в сравнении BUFFERTYPE m_nBufferType[2];... // Handle unnamed buffers if ((m_nBufferType[nBuffer] == BUFFER_UNNAMED) || (m_nBufferType[nBuffer] == BUFFER_UNNAMED)) nSaveErrorCode = SAVE_NO_FILENAME; WinMerge свободное ПО с открытым исходным кодом для сравнения и синхронизации файлов и директорий. Если посмотреть код рядом, то по аналогии здесь должно быть: (m_nBufferType[0] == BUFFER_UNNAMED) || (m_nBufferType[1] == BUFFER_UNNAMED)

Забытый индекс массива IPP Samples - примеры, демонстрирующие работу с библиотекой Intel Performance Primitives Library 7.0. void lNormalizeVector_32f_P3IM(..., Ipp32s* mask,...) { Ipp32s i; Ipp32f norm; for(i=0; i

Одинаковые ветви кода Notepad++ - свободный текстовый редактор для Windows с подсветкой синтаксиса большого количества языков программирования и разметки. if (!_isVertical) Flags |= DT_VCENTER; else Flags |= DT_BOTTOM; if (!_isVertical) Flags |= DT_BOTTOM; else Flags |= DT_BOTTOM;

Вызов неверной функции со схожим именем /** Deletes all previous field specifiers. * This should be used when dealing * with clients that send multiple NEP_PACKET_SPEC * messages, so only the last PacketSpec is taken * into account. */ int NEPContext::resetClientFieldSpecs(){ this->fspecs.empty(); return OP_SUCCESS; } /* End of resetClientFieldSpecs() */ Какой замечательный комментарий. Жаль только не то делаем, что хотим. Nmap Security Scanner - свободная утилита, предназначенная для разнообразного настраиваемого сканирования IP-сетей с любым количеством объектов, определения состояния объектов сканируемой сети.

Опасный оператор ?: Newton Game Dynamics - популярный физический движок, который предоставляет надежное и быстрое решение для симуляции физического поведения объектов окружающей среды. den = dgFloat32 (1.0e-24f) * (den > dgFloat32(0.0f)) ? dgFloat32(1.0f) : dgFloat32(-1.0f); Приоритет оператора ?: ниже, чем у оператора умножения *.

И так далее, и так далее… if (m_szPassword != NULL) { if (m_szPassword != '\0') { if (*m_szPassword != '\0') Библиотека Ultimate TCP/IP bleeding = 0; bleedx = 0,bleedy; direction = 0; Lugaru bleedx = 0; bleedy = 0;

И так далее, и так далее… FCE Ultra if((t=(char *)realloc( next->name, strlen(name+1)))) if((t=(char *)realloc( next->name, strlen(name)+1))) minX=max(0,minX+mcLeftStart-2); minY=max(0,minY+mcTopStart-2); maxX=min((int)width,maxX+mcRightEnd-1); maxY=min((int)height,maxX+mcBottomEnd-1); minX=max(0,minX+mcLeftStart-2); minY=max(0,minY+mcTopStart-2); maxX=min((int)width,maxX+mcRightEnd-1); maxY=min((int)height,maxY+mcBottomEnd-1);

Низкоуровневые операции работы с памятью ZeroMemory; memset; memcpy; memcmp; … Хочется отдельно остановиться на наследии программ на Си, где использовались функции:

Низкоуровневые операции работы с памятью ID_INLINE mat3_t::mat3_t( float src[3][3] ) { memcpy( mat, src, sizeof( src ) ); } Return to Castle Wolfenstein itemInfo_t *itemInfo; memset( itemInfo, 0, sizeof( &itemInfo ) ); memset( itemInfo, 0, sizeof( *itemInfo ) ); ID_INLINE mat3_t::mat3_t( float (&src)[3][3] ) { memcpy( mat, src, sizeof( src ) ); }

Низкоуровневые операции работы с памятью CxImage - открытая библиотека обработки изображений. memset(tcmpt->stepsizes, 0, sizeof(tcmpt->numstepsizes * sizeof(uint_fast16_t))); memset(tcmpt->stepsizes, 0, tcmpt->numstepsizes * sizeof(uint_fast16_t));

Низкоуровневые операции работы с памятью dgInt32 faceOffsetHitogram[256]; dgSubMesh* mainSegmenst[256]; memset (faceOffsetHitogram, 0, sizeof (faceOffsetHitogram)); memset (mainSegmenst, 0, sizeof (faceOffsetHitogram)); Скопировали код и не полностью поправили. В результате в Win64 размер указателя станет не равен размеру типа dgInt32 и мы очистим только часть массива mainSegmenst. Красивый пример 64-битной ошибки:

Низкоуровневые операции работы с памятью #define CONT_MAP_MAX 50 int _iContMap[CONT_MAP_MAX];... memset(_iContMap, -1, CONT_MAP_MAX); memset(_iContMap, -1, CONT_MAP_MAX * sizeof(int));

Низкоуровневые операции работы с памятью Да, сейчас это не ошибка. Но это мина! Real w, x, y, z;... inline Quaternion(Real* valptr) { memcpy(&w, valptr, sizeof(Real)*4); } OGRE (Object-Oriented Graphics Rendering Engine) - объектно-ориентированный графический движок с открытым исходным кодом, написанный на C++.

Чем раньше – тем лучше

Почему все-таки не только юнит-тесты? проверка мест, редко получающих управления; обнаружение плавающих ошибок (undefined behavior, гейзенбаги); не на все варианты кода можно написать юнит-тест: – сложные счетные алгоритмы; – интерфейс.

Здесь не поможет юнит-тест, но поможет статический анализ OPENFILENAME lofn;... lofn.lpstrFilter = uni("All Files (*.*)\0*.*"); Fennec Media Project - универсальный медиа- плеер ориентированный на воспроизведение аудио и видео в высоком разрешении. lofn.lpstrFilter = uni("All Files (*.*)\0*.*\0");

Здесь не поможет юнит-тест, но поможет статический анализ static INT_PTR CALLBACK DlgProcTrayOpts(...) {... EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),TRUE); EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLE),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_MULTITRAY),FALSE);... }

Где подробнее узнать про PVS-Studio? PVS-Studio - статический анализатор, выявляющий ошибки в исходном коде приложений на языке C/C++/C++0x. Страница продукта: Демонстрационная версия: download/ download/ Документация на русском языке: PVS-Studio интегрируется в среду разработки Visual Studio 2005/2008/2010.

Вопросы ? Контактная информация: Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации» Сайт: Тел.: +7 (4872) (GMT + 03:00) Twitter: