SlideShare a Scribd company logo
Опыт разработки статического
анализатора кода
Автор: Андрей Карпов
www.viva64.com
1
Статический анализ кода
• Суть: автоматический Code-Review
• Преимущества и недостатки
2
HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) {
Data16bitsDirective = "t.halft";
Data32bitsDirective = "t.wordt";
Data64bitsDirective = nullptr;
ZeroDirective = "t.skipt";
CommentString = "//";
LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
InlineAsmStart = "# InlineAsm Start";
InlineAsmEnd = "# InlineAsm End";
ZeroDirective = "t.spacet";
AscizDirective = "t.stringt";
Ошибка в проекте Clang
3
HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) {
Data16bitsDirective = "t.halft";
Data32bitsDirective = "t.wordt";
Data64bitsDirective = nullptr;
ZeroDirective = "t.skipt";
CommentString = "//";
LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment;
InlineAsmStart = "# InlineAsm Start";
InlineAsmEnd = "# InlineAsm End";
ZeroDirective = "t.spacet";
AscizDirective = "t.stringt";
Ошибка в проекте Clang
PVS-Studio: V519 The 'ZeroDirective' variable is assigned values twice successively.
Perhaps this is a mistake. Check lines: 25, 31. HexagonMCAsmInfo.cpp 31
4
Ошибка в проекте StarEngine
PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header,
uintptr_t header_mask, int value)
{
char buf[128];
sprintf(buf, "%d", value);
return set_value_buffer(dest, header, header_mask, buf);
}
5
Ошибка в проекте StarEngine
#define sfstream std::fstream
#define schar char
#define suchar unsigned schar
#define sprintf std::printf
#define satof atof
#define satoi atoi
PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header,
uintptr_t header_mask, int value)
{
char buf[128];
sprintf(buf, "%d", value);
return set_value_buffer(dest, header, header_mask, buf);
}
PVS-Studio: V614 Uninitialized buffer 'buf' used. pugixml.cpp 3362
6
Проблема айсберга
7
Привет из прошлого: простые инструменты
и плохие стандарты
• RATS
• Cppcheck
• MISRA C
8
Регулярные выражения не работают
• Сложно искать даже простейшие перестановки: (A + B == B + A);
• Макросы: кто их раскроет?
• Типы: кто вычислит цепочку typedef?
• Значения: как узнать, что индекс вышел за границу массива?
9
Регулярные выражения не работают
Моё терпение лопнуло ещё в 2010 году, и я написал критическую
статью: «Статический анализ и регулярные выражения»
https://www.viva64.com/ru/b/0087/
10
Что внутри современных
статических анализаторов кода
на примере PVS-Studio
11
Вывод типов (type inference)
• Информации о типах нужна для реализации большинства
диагностик
• Нужно уметь выводить типы из цепочки typedef
• Нужно уметь подставлять типы (и константы) для анализа
шаблонов
typedef
12
Вывод типов (type inference)
template<class T, size_t N> struct X
{
T A[N];
void Foo()
{
memset(A, 0, sizeof(T) * 10);
}
};
13
Вывод типов (type inference)
template<class T, size_t N> struct X
{
T A[N];
void Foo()
{
memset(A, 0, sizeof(T) * 10);
}
};
void Do()
{
X<int, 5> a;
a.Foo();
}
PVS-Studio: V512 CWE-119 Instantiate X < int, 5 >: A call of
the 'memset' function will lead to overflow of the buffer
'A'. test.cpp 127
14
Анализ потока данных (data-flow analysis)
int cache_lookup_path(...., vnode_t dp, ....)
{
....
if (dp && (dp->v_flag & VISHARDLINK)) {
break;
}
if ((dp->v_flag & VROOT) ||
dp == ndp->ni_rootdir ||
dp->v_parent == NULLVP)
break;
....
}
Ошибка в проекте
XNU kernel
PVS-Studio: V522 CWE-690 There might be dereferencing of a
potential null pointer 'dp'. vfs_cache.c 1449
15
static const int kDaysInMonth[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
bool ValidateDateTime(const DateTime& time) {
if (time.year < 1 || time.year > 9999 ||
time.month < 1 || time.month > 12 ||
time.day < 1 || time.day > 31 ||
time.hour < 0 || time.hour > 23 ||
time.minute < 0 || time.minute > 59 ||
time.second < 0 || time.second > 59) {
return false;
}
if (time.month == 2 && IsLeapYear(time.year)) {
return time.month <= kDaysInMonth[time.month] + 1;
} else {
return time.month <= kDaysInMonth[time.month];
}
} 16
static const int kDaysInMonth[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
bool ValidateDateTime(const DateTime& time) {
if (time.year < 1 || time.year > 9999 ||
time.month < 1 || time.month > 12 ||
time.day < 1 || time.day > 31 ||
time.hour < 0 || time.hour > 23 ||
time.minute < 0 || time.minute > 59 ||
time.second < 0 || time.second > 59) {
return false;
}
if (time.month == 2 && IsLeapYear(time.year)) {
return time.month <= kDaysInMonth[time.month] + 1;
} else {
return time.month <= kDaysInMonth[time.month];
}
} 17
static const int kDaysInMonth[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
bool ValidateDateTime(const DateTime& time) {
if (time.year < 1 || time.year > 9999 ||
time.month < 1 || time.month > 12 ||
time.day < 1 || time.day > 31 ||
time.hour < 0 || time.hour > 23 ||
time.minute < 0 || time.minute > 59 ||
time.second < 0 || time.second > 59) {
return false;
}
if (time.month == 2 && IsLeapYear(time.year)) {
return time.month <= kDaysInMonth[time.month] + 1;
} else {
return time.month <= kDaysInMonth[time.month];
}
} 18
static const int kDaysInMonth[13] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
bool ValidateDateTime(const DateTime& time) {
if (time.year < 1 || time.year > 9999 ||
time.month < 1 || time.month > 12 ||
time.day < 1 || time.day > 31 ||
time.hour < 0 || time.hour > 23 ||
time.minute < 0 || time.minute > 59 ||
time.second < 0 || time.second > 59) {
return false;
}
if (time.month == 2 && IsLeapYear(time.year)) {
return time.month <= kDaysInMonth[time.month] + 1;
} else {
return time.month <= kDaysInMonth[time.month];
}
} time.day
Ошибка в проекте
protobuf
(Chromium)
19
Анализ потока данных (data-flow analysis)
• CoreHard Spring 2018. Павел Беликов. Как работает анализ Data
Flow в статическом анализаторе кода
https://youtu.be/nrQUpGM9vYQ
20
Символьное выполнение (symbolic execution)
void F(int X)
{
int A = X;
int B = X + 10;
int Q[5];
Q[B - A] = 1;
}
PVS-Studio: V557 CWE-787 Array overrun is possible. The 'B - A' index is pointing
beyond array bound. test.cpp 126
21
Символьное выполнение (symbolic execution)
PVS-Studio: V547 CWE-571 Expression 'A < C' is always true. test.cpp 137
void F(int A, int B, int C)
{
if (A < B)
if (B < C)
if (A < C)
foo();
}
22
Сопоставление с шаблоном
(pattern-based analysis)
Ошибка в Linux Kernel
static ssize_t lp8788_show_eoc_time(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lp8788_charger *pchg = dev_get_drvdata(dev);
char *stime[] = { "400ms", "5min", "10min", "15min",
"20min", "25min", "30min" "No timeout" };
....
}
PVS-Studio: V653 A suspicious string consisting of two parts is used for
array initialization. It is possible that a comma is missing. Consider
inspecting this literal: "30min" "No timeout". lp8788-charger.c 657
23
Сопоставление с шаблоном
(pattern-based analysis)
Ошибка в проекте
WebRTC
void AsyncSocksProxySocket::SendAuth() {
....
char * sensitive = new char[len];
pass_.CopyTo(sensitive, true);
request.WriteString(sensitive); // Password
memset(sensitive, 0, len);
delete [] sensitive;
DirectSend(request.Data(), request.Length());
state_ = SS_AUTH;
}
PVS-Studio: V597 CWE-14 The compiler could delete the 'memset' function
call, which is used to flush 'sensitive' object. The RtlSecureZeroMemory()
function should be used to erase the private data. socketadapters.cc 677 24
Аннотирование методов (method annotations)
Любая достаточно развитая технология
неотличима от магии
(c) Артур Кларк
25
Аннотирование методов (method annotations)
• Статический анализ – это не магия, а большая работа
• Например, в PVS-Studio размечено 7140 функций
(и это я посчитал только для C и C++)
26
Аннотирование методов (method annotations)
• WinAPI
• стандартная библиотека C,
• стандартная библиотека шаблонов (STL),
• glibc (GNU C Library)
• Qt
• MFC
• zlib
• libpng
• OpenSSL
• и так далее
27
28
Пример аннотирования функции fread
C_"size_t fread(void * _DstBuf, size_t _ElementSize, size_t _Count, FILE * _File);"
C_"size_t std::fread(void * _DstBuf, size_t _ElementSize, size_t _Count, FILE * _File);"
ADD(HAVE_STATE | RET_SKIP | F_MODIFY_PTR_1, nullptr, nullptr, "fread",
POINTER_1, BYTE_COUNT, COUNT, POINTER_2).
Add_Read(from_2_3, to_return, buf_1).Add_DataSafetyStatusRelations(0, 3);
ADD(HAVE_STATE | RET_SKIP | F_MODIFY_PTR_1, "std", nullptr, "fread",
POINTER_1, BYTE_COUNT, COUNT, POINTER_2).
Add_Read(from_2_3, to_return, buf_1).Add_DataSafetyStatusRelations(0, 3);
29
Пример аннотирования функции fread
define MAX_AVISYNTH_SCRIPT_LENGTH 16384
void TavisynthPage::onLoad(void)
{
....
char script[MAX_AVISYNTH_SCRIPT_LENGTH];
size_t len = fread(script, 1, MAX_AVISYNTH_SCRIPT_LENGTH, f);
fclose(f);
script[len] = '0';
....
}
Ошибка в проекте
ffdshow
30
Пример аннотирования функции fread
define MAX_AVISYNTH_SCRIPT_LENGTH 16384
void TavisynthPage::onLoad(void)
{
....
char script[MAX_AVISYNTH_SCRIPT_LENGTH];
size_t len = fread(script, 1, MAX_AVISYNTH_SCRIPT_LENGTH, f);
fclose(f);
script[len] = '0';
....
}
Ошибка в проекте
ffdshow
PVS-Studio: V557 Array overrun is possible. The value of 'len' index
could reach 16384. cavisynth.cpp 129
31
Автоматическое аннотирование функций
inline uint32_t bswap32(uint32_t pData) {
return
(((pData & 0xFF000000) >> 24) | ((pData & 0x00FF0000) >> 8) |
((pData & 0x0000FF00) << 8) | ((pData & 0x000000FF) << 24));
}
Ошибка в проекте Android
32
Автоматическое аннотирование функций
Ошибка в проекте Android
bool ELFAttribute::merge(....) {
....
uint32_t subsection_length =
*reinterpret_cast<const uint32_t*>(subsection_data);
if (llvm::sys::IsLittleEndianHost !=
m_Config.targets().isLittleEndian())
bswap32(subsection_length);
....
}
PVS-Studio: V530 CWE-252 The return value of function 'bswap32' is required to be
utilized. ELFAttribute.cpp 84
33
Смесь технологий
int Div(int X)
{
return 10 / X;
}
void Foo()
{
for (int i = 0; i < 5; ++i)
Div(i);
}
PVS-Studio: V609 CWE-628 Divide by zero. Denominator 'X' == 0.
The 'Div' function processes value '[0..4]'. Inspect the first
argument. Check lines: 106, 110. test.cpp 106
Автоматическое аннотирование
+
Анализ потока управления
34
О машинном обучении
35
Зачем учить, когда можно
просто вычислить?
Обучение vs Data Flow анализ
36
y = sin(x)
37
Невероятное количество способов
получить нулевой указатель
• p = x ? array : nullptr;
• if (x) p = array; else p = nullptr;
• p = malloc(n);
char *p;
switch (x)
{
case 1: p = "foo"; break;
default: p = strstr(str, "tag"); break;
}
38
Огромное количество способов
разыменовать нулевой указатель
• *p
• p[i]
• p->foo()
• memset(p, 0, n);
• int *x = p; *x = 123;
• T* x = new(p) T;
39
Зачем учить, если можно точно вычислить?
• деление на 0;
• разыменовывание нулевого указателя;
• выход за границу массива;
• переполнения;
• условие всегда истинно/ложно;
• и т.д.
• Более того, программисты сами ищут подобные ошибки,
«выполняя код в голове»
40
Обучение vs Pattern Matching
41
Вторая проблема: мало примеров
• Да, можно научить искать некоторые случаи, которые выявляются
технологией сопоставления с шаблоном
• Но где взять столько примеров?
42
Язык C++ быстро меняется.
Как искать ошибки в коде, где
использован новый синтаксис?
43
44
Машинное обучение бесполезно?
• Нет, но слишком много «хайпа»
• Интересное на мой взгляд направление: фильтрация ложных
предупреждений
45
Заключение
• Статический анализ – это сложно и интересно
• Анализаторы сейчас и 10 лет назад – это две большие разницы
• Внедрение статического анализа неизбежно из-за роста размеров
и сложности проектов
• также, как это было с системами контроля версий
• также, как это было с багтрекерами
46
Ответы на вопросы
E-Mail: karpov@viva64.com
Twitter: @Code_Analysis
Instagram: @pvs_studio_unicorn
47

More Related Content

What's hot

Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Sergey Platonov
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Yauheni Akhotnikau
 
Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”
Platonov Sergey
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Sergey Platonov
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
Eugeniy Tyumentcev
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Platonov Sergey
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Sergey Platonov
 
разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2
Eugeniy Tyumentcev
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
Sergey Platonov
 
Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!
RAMBLER&Co
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
Alexey Paznikov
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++
Sergey Platonov
 
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
Alexey Paznikov
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonovComputer Science Club
 
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Platonov Sergey
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
Alexey Paznikov
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
Mikhail Kurnosov
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в форме
Ilia Shishkov
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
corehard_by
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Sergey Platonov
 

What's hot (20)

Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”Михаил Матросов, “С++ без new и delete”
Михаил Матросов, “С++ без new и delete”
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3разработка серверов и серверных приложений лекция №3
разработка серверов и серверных приложений лекция №3
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
 
разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2разработка серверов и серверных приложений лекция №2
разработка серверов и серверных приложений лекция №2
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
 
Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!Rambler.iOS #9: Анализируй это!
Rambler.iOS #9: Анализируй это!
 
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
ПВТ - осень 2014 - Лекция 7. Многопоточное программирование без блокировок. М...
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++
 
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
ПВТ - весна 2015 - Лекция 8. Многопоточное программирование без использования...
 
20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov20130429 dynamic c_c++_program_analysis-alexey_samsonov
20130429 dynamic c_c++_program_analysis-alexey_samsonov
 
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
Игорь Кудрин, «Используем неизменяемые данные и создаем качественный код»
 
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
ПВТ - весна 2015 - Лекция 5. Многопоточное программирование в С++. Синхрониза...
 
Лекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building BlocksЛекция 8. Intel Threading Building Blocks
Лекция 8. Intel Threading Building Blocks
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в форме
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтерыСовременный статический анализ кода: что умеет он, чего не умели линтеры
Современный статический анализ кода: что умеет он, чего не умели линтеры
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 

Similar to Опыт разработки статического анализатора кода

Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...
Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...
Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...
Andrey Karpov
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?
Andrey Karpov
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кодаAndrey Karpov
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
Pavel Tsukanov
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минут
Andrey Karpov
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программиста
Andrey Karpov
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Yandex
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
Andrey Karpov
 
Статический анализ: ищем ошибки... и уязвимости?
Статический анализ: ищем ошибки... и уязвимости?Статический анализ: ищем ошибки... и уязвимости?
Статический анализ: ищем ошибки... и уязвимости?
Andrey Karpov
 
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
Andrey Karpov
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x Introduction
Fedor Vompe
 
PVS-Studio в 2019
PVS-Studio в 2019PVS-Studio в 2019
PVS-Studio в 2019
Andrey Karpov
 
Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...
Andrey Karpov
 
Intel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибкамиIntel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибками
Tatyanazaxarova
 
Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1
m2rus
 
Пояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteПояснения к статье про Copy-Paste
Пояснения к статье про Copy-Paste
Tatyanazaxarova
 
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Andrey Karpov
 
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Tatyanazaxarova
 
Parallel STL
Parallel STLParallel STL
Parallel STL
Evgeny Krutko
 
«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...
«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...
«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...
Mail.ru Group
 

Similar to Опыт разработки статического анализатора кода (20)

Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...
Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...
Выявление ошибок и потенциальных уязвимостей в C и C++ коде с помощью анализа...
 
Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?Статический анализ кода: Что? Как? Зачем?
Статический анализ кода: Что? Как? Зачем?
 
статический анализ кода
статический анализ кодастатический анализ кода
статический анализ кода
 
Статический анализ кода
Статический анализ кода Статический анализ кода
Статический анализ кода
 
Статический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минутСтатический анализ: вокруг Java за 60 минут
Статический анализ: вокруг Java за 60 минут
 
Всё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программистаВсё о статическом анализе кода для Java программиста
Всё о статическом анализе кода для Java программиста
 
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
Евгений Крутько — Опыт внедрения технологий параллельных вычислений для повыш...
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Статический анализ: ищем ошибки... и уязвимости?
Статический анализ: ищем ошибки... и уязвимости?Статический анализ: ищем ошибки... и уязвимости?
Статический анализ: ищем ошибки... и уязвимости?
 
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x Introduction
 
PVS-Studio в 2019
PVS-Studio в 2019PVS-Studio в 2019
PVS-Studio в 2019
 
Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...Улучшение качества открытого программного обеспечения с помощью инструментов ...
Улучшение качества открытого программного обеспечения с помощью инструментов ...
 
Intel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибкамиIntel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибками
 
Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1Основы и применение статического анализа кода при разработке лекция 1
Основы и применение статического анализа кода при разработке лекция 1
 
Пояснения к статье про Copy-Paste
Пояснения к статье про Copy-PasteПояснения к статье про Copy-Paste
Пояснения к статье про Copy-Paste
 
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
 
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...
«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...
«Статический анализ: гордость и предубеждения», Алексей Кузьменко, аналитик И...
 

More from Andrey Karpov

60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста
Andrey Karpov
 
60 terrible tips for a C++ developer
60 terrible tips for a C++ developer60 terrible tips for a C++ developer
60 terrible tips for a C++ developer
Andrey Karpov
 
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Andrey Karpov
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
Andrey Karpov
 
PVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewPVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature Overview
Andrey Karpov
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
Andrey Karpov
 
PVS-Studio в 2021
PVS-Studio в 2021PVS-Studio в 2021
PVS-Studio в 2021
Andrey Karpov
 
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Andrey Karpov
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
Andrey Karpov
 
Does static analysis need machine learning?
Does static analysis need machine learning?Does static analysis need machine learning?
Does static analysis need machine learning?
Andrey Karpov
 
Typical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaTypical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and Java
Andrey Karpov
 
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
Andrey Karpov
 
Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?
Andrey Karpov
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
Andrey Karpov
 
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareThe Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
Andrey Karpov
 
Static Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal EngineStatic Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal Engine
Andrey Karpov
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Andrey Karpov
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++
Andrey Karpov
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?
Andrey Karpov
 
Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for you
Andrey Karpov
 

More from Andrey Karpov (20)

60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста60 антипаттернов для С++ программиста
60 антипаттернов для С++ программиста
 
60 terrible tips for a C++ developer
60 terrible tips for a C++ developer60 terrible tips for a C++ developer
60 terrible tips for a C++ developer
 
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...Ошибки, которые сложно заметить на code review, но которые находятся статичес...
Ошибки, которые сложно заметить на code review, но которые находятся статичес...
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
 
PVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature OverviewPVS-Studio in 2021 - Feature Overview
PVS-Studio in 2021 - Feature Overview
 
PVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибокPVS-Studio в 2021 - Примеры ошибок
PVS-Studio в 2021 - Примеры ошибок
 
PVS-Studio в 2021
PVS-Studio в 2021PVS-Studio в 2021
PVS-Studio в 2021
 
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
Make Your and Other Programmer’s Life Easier with Static Analysis (Unreal Eng...
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
 
Does static analysis need machine learning?
Does static analysis need machine learning?Does static analysis need machine learning?
Does static analysis need machine learning?
 
Typical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and JavaTypical errors in code on the example of C++, C#, and Java
Typical errors in code on the example of C++, C#, and Java
 
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
How to Fix Hundreds of Bugs in Legacy Code and Not Die (Unreal Engine 4)
 
Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?Game Engine Code Quality: Is Everything Really That Bad?
Game Engine Code Quality: Is Everything Really That Bad?
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source SoftwareThe Use of Static Code Analysis When Teaching or Developing Open-Source Software
The Use of Static Code Analysis When Teaching or Developing Open-Source Software
 
Static Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal EngineStatic Code Analysis for Projects, Built on Unreal Engine
Static Code Analysis for Projects, Built on Unreal Engine
 
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded SystemsSafety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
Safety on the Max: How to Write Reliable C/C++ Code for Embedded Systems
 
The Great and Mighty C++
The Great and Mighty C++The Great and Mighty C++
The Great and Mighty C++
 
Static code analysis: what? how? why?
Static code analysis: what? how? why?Static code analysis: what? how? why?
Static code analysis: what? how? why?
 
Zero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for youZero, one, two, Freddy's coming for you
Zero, one, two, Freddy's coming for you
 

Опыт разработки статического анализатора кода

  • 1. Опыт разработки статического анализатора кода Автор: Андрей Карпов www.viva64.com 1
  • 2. Статический анализ кода • Суть: автоматический Code-Review • Преимущества и недостатки 2
  • 3. HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) { Data16bitsDirective = "t.halft"; Data32bitsDirective = "t.wordt"; Data64bitsDirective = nullptr; ZeroDirective = "t.skipt"; CommentString = "//"; LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment; InlineAsmStart = "# InlineAsm Start"; InlineAsmEnd = "# InlineAsm End"; ZeroDirective = "t.spacet"; AscizDirective = "t.stringt"; Ошибка в проекте Clang 3
  • 4. HexagonMCAsmInfo::HexagonMCAsmInfo(const Triple &TT) { Data16bitsDirective = "t.halft"; Data32bitsDirective = "t.wordt"; Data64bitsDirective = nullptr; ZeroDirective = "t.skipt"; CommentString = "//"; LCOMMDirectiveAlignmentType = LCOMM::ByteAlignment; InlineAsmStart = "# InlineAsm Start"; InlineAsmEnd = "# InlineAsm End"; ZeroDirective = "t.spacet"; AscizDirective = "t.stringt"; Ошибка в проекте Clang PVS-Studio: V519 The 'ZeroDirective' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 25, 31. HexagonMCAsmInfo.cpp 31 4
  • 5. Ошибка в проекте StarEngine PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, int value) { char buf[128]; sprintf(buf, "%d", value); return set_value_buffer(dest, header, header_mask, buf); } 5
  • 6. Ошибка в проекте StarEngine #define sfstream std::fstream #define schar char #define suchar unsigned schar #define sprintf std::printf #define satof atof #define satoi atoi PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, int value) { char buf[128]; sprintf(buf, "%d", value); return set_value_buffer(dest, header, header_mask, buf); } PVS-Studio: V614 Uninitialized buffer 'buf' used. pugixml.cpp 3362 6
  • 8. Привет из прошлого: простые инструменты и плохие стандарты • RATS • Cppcheck • MISRA C 8
  • 9. Регулярные выражения не работают • Сложно искать даже простейшие перестановки: (A + B == B + A); • Макросы: кто их раскроет? • Типы: кто вычислит цепочку typedef? • Значения: как узнать, что индекс вышел за границу массива? 9
  • 10. Регулярные выражения не работают Моё терпение лопнуло ещё в 2010 году, и я написал критическую статью: «Статический анализ и регулярные выражения» https://www.viva64.com/ru/b/0087/ 10
  • 11. Что внутри современных статических анализаторов кода на примере PVS-Studio 11
  • 12. Вывод типов (type inference) • Информации о типах нужна для реализации большинства диагностик • Нужно уметь выводить типы из цепочки typedef • Нужно уметь подставлять типы (и константы) для анализа шаблонов typedef 12
  • 13. Вывод типов (type inference) template<class T, size_t N> struct X { T A[N]; void Foo() { memset(A, 0, sizeof(T) * 10); } }; 13
  • 14. Вывод типов (type inference) template<class T, size_t N> struct X { T A[N]; void Foo() { memset(A, 0, sizeof(T) * 10); } }; void Do() { X<int, 5> a; a.Foo(); } PVS-Studio: V512 CWE-119 Instantiate X < int, 5 >: A call of the 'memset' function will lead to overflow of the buffer 'A'. test.cpp 127 14
  • 15. Анализ потока данных (data-flow analysis) int cache_lookup_path(...., vnode_t dp, ....) { .... if (dp && (dp->v_flag & VISHARDLINK)) { break; } if ((dp->v_flag & VROOT) || dp == ndp->ni_rootdir || dp->v_parent == NULLVP) break; .... } Ошибка в проекте XNU kernel PVS-Studio: V522 CWE-690 There might be dereferencing of a potential null pointer 'dp'. vfs_cache.c 1449 15
  • 16. static const int kDaysInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool ValidateDateTime(const DateTime& time) { if (time.year < 1 || time.year > 9999 || time.month < 1 || time.month > 12 || time.day < 1 || time.day > 31 || time.hour < 0 || time.hour > 23 || time.minute < 0 || time.minute > 59 || time.second < 0 || time.second > 59) { return false; } if (time.month == 2 && IsLeapYear(time.year)) { return time.month <= kDaysInMonth[time.month] + 1; } else { return time.month <= kDaysInMonth[time.month]; } } 16
  • 17. static const int kDaysInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool ValidateDateTime(const DateTime& time) { if (time.year < 1 || time.year > 9999 || time.month < 1 || time.month > 12 || time.day < 1 || time.day > 31 || time.hour < 0 || time.hour > 23 || time.minute < 0 || time.minute > 59 || time.second < 0 || time.second > 59) { return false; } if (time.month == 2 && IsLeapYear(time.year)) { return time.month <= kDaysInMonth[time.month] + 1; } else { return time.month <= kDaysInMonth[time.month]; } } 17
  • 18. static const int kDaysInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool ValidateDateTime(const DateTime& time) { if (time.year < 1 || time.year > 9999 || time.month < 1 || time.month > 12 || time.day < 1 || time.day > 31 || time.hour < 0 || time.hour > 23 || time.minute < 0 || time.minute > 59 || time.second < 0 || time.second > 59) { return false; } if (time.month == 2 && IsLeapYear(time.year)) { return time.month <= kDaysInMonth[time.month] + 1; } else { return time.month <= kDaysInMonth[time.month]; } } 18
  • 19. static const int kDaysInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool ValidateDateTime(const DateTime& time) { if (time.year < 1 || time.year > 9999 || time.month < 1 || time.month > 12 || time.day < 1 || time.day > 31 || time.hour < 0 || time.hour > 23 || time.minute < 0 || time.minute > 59 || time.second < 0 || time.second > 59) { return false; } if (time.month == 2 && IsLeapYear(time.year)) { return time.month <= kDaysInMonth[time.month] + 1; } else { return time.month <= kDaysInMonth[time.month]; } } time.day Ошибка в проекте protobuf (Chromium) 19
  • 20. Анализ потока данных (data-flow analysis) • CoreHard Spring 2018. Павел Беликов. Как работает анализ Data Flow в статическом анализаторе кода https://youtu.be/nrQUpGM9vYQ 20
  • 21. Символьное выполнение (symbolic execution) void F(int X) { int A = X; int B = X + 10; int Q[5]; Q[B - A] = 1; } PVS-Studio: V557 CWE-787 Array overrun is possible. The 'B - A' index is pointing beyond array bound. test.cpp 126 21
  • 22. Символьное выполнение (symbolic execution) PVS-Studio: V547 CWE-571 Expression 'A < C' is always true. test.cpp 137 void F(int A, int B, int C) { if (A < B) if (B < C) if (A < C) foo(); } 22
  • 23. Сопоставление с шаблоном (pattern-based analysis) Ошибка в Linux Kernel static ssize_t lp8788_show_eoc_time(struct device *dev, struct device_attribute *attr, char *buf) { struct lp8788_charger *pchg = dev_get_drvdata(dev); char *stime[] = { "400ms", "5min", "10min", "15min", "20min", "25min", "30min" "No timeout" }; .... } PVS-Studio: V653 A suspicious string consisting of two parts is used for array initialization. It is possible that a comma is missing. Consider inspecting this literal: "30min" "No timeout". lp8788-charger.c 657 23
  • 24. Сопоставление с шаблоном (pattern-based analysis) Ошибка в проекте WebRTC void AsyncSocksProxySocket::SendAuth() { .... char * sensitive = new char[len]; pass_.CopyTo(sensitive, true); request.WriteString(sensitive); // Password memset(sensitive, 0, len); delete [] sensitive; DirectSend(request.Data(), request.Length()); state_ = SS_AUTH; } PVS-Studio: V597 CWE-14 The compiler could delete the 'memset' function call, which is used to flush 'sensitive' object. The RtlSecureZeroMemory() function should be used to erase the private data. socketadapters.cc 677 24
  • 25. Аннотирование методов (method annotations) Любая достаточно развитая технология неотличима от магии (c) Артур Кларк 25
  • 26. Аннотирование методов (method annotations) • Статический анализ – это не магия, а большая работа • Например, в PVS-Studio размечено 7140 функций (и это я посчитал только для C и C++) 26
  • 27. Аннотирование методов (method annotations) • WinAPI • стандартная библиотека C, • стандартная библиотека шаблонов (STL), • glibc (GNU C Library) • Qt • MFC • zlib • libpng • OpenSSL • и так далее 27
  • 28. 28
  • 29. Пример аннотирования функции fread C_"size_t fread(void * _DstBuf, size_t _ElementSize, size_t _Count, FILE * _File);" C_"size_t std::fread(void * _DstBuf, size_t _ElementSize, size_t _Count, FILE * _File);" ADD(HAVE_STATE | RET_SKIP | F_MODIFY_PTR_1, nullptr, nullptr, "fread", POINTER_1, BYTE_COUNT, COUNT, POINTER_2). Add_Read(from_2_3, to_return, buf_1).Add_DataSafetyStatusRelations(0, 3); ADD(HAVE_STATE | RET_SKIP | F_MODIFY_PTR_1, "std", nullptr, "fread", POINTER_1, BYTE_COUNT, COUNT, POINTER_2). Add_Read(from_2_3, to_return, buf_1).Add_DataSafetyStatusRelations(0, 3); 29
  • 30. Пример аннотирования функции fread define MAX_AVISYNTH_SCRIPT_LENGTH 16384 void TavisynthPage::onLoad(void) { .... char script[MAX_AVISYNTH_SCRIPT_LENGTH]; size_t len = fread(script, 1, MAX_AVISYNTH_SCRIPT_LENGTH, f); fclose(f); script[len] = '0'; .... } Ошибка в проекте ffdshow 30
  • 31. Пример аннотирования функции fread define MAX_AVISYNTH_SCRIPT_LENGTH 16384 void TavisynthPage::onLoad(void) { .... char script[MAX_AVISYNTH_SCRIPT_LENGTH]; size_t len = fread(script, 1, MAX_AVISYNTH_SCRIPT_LENGTH, f); fclose(f); script[len] = '0'; .... } Ошибка в проекте ffdshow PVS-Studio: V557 Array overrun is possible. The value of 'len' index could reach 16384. cavisynth.cpp 129 31
  • 32. Автоматическое аннотирование функций inline uint32_t bswap32(uint32_t pData) { return (((pData & 0xFF000000) >> 24) | ((pData & 0x00FF0000) >> 8) | ((pData & 0x0000FF00) << 8) | ((pData & 0x000000FF) << 24)); } Ошибка в проекте Android 32
  • 33. Автоматическое аннотирование функций Ошибка в проекте Android bool ELFAttribute::merge(....) { .... uint32_t subsection_length = *reinterpret_cast<const uint32_t*>(subsection_data); if (llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian()) bswap32(subsection_length); .... } PVS-Studio: V530 CWE-252 The return value of function 'bswap32' is required to be utilized. ELFAttribute.cpp 84 33
  • 34. Смесь технологий int Div(int X) { return 10 / X; } void Foo() { for (int i = 0; i < 5; ++i) Div(i); } PVS-Studio: V609 CWE-628 Divide by zero. Denominator 'X' == 0. The 'Div' function processes value '[0..4]'. Inspect the first argument. Check lines: 106, 110. test.cpp 106 Автоматическое аннотирование + Анализ потока управления 34
  • 36. Зачем учить, когда можно просто вычислить? Обучение vs Data Flow анализ 36
  • 38. Невероятное количество способов получить нулевой указатель • p = x ? array : nullptr; • if (x) p = array; else p = nullptr; • p = malloc(n); char *p; switch (x) { case 1: p = "foo"; break; default: p = strstr(str, "tag"); break; } 38
  • 39. Огромное количество способов разыменовать нулевой указатель • *p • p[i] • p->foo() • memset(p, 0, n); • int *x = p; *x = 123; • T* x = new(p) T; 39
  • 40. Зачем учить, если можно точно вычислить? • деление на 0; • разыменовывание нулевого указателя; • выход за границу массива; • переполнения; • условие всегда истинно/ложно; • и т.д. • Более того, программисты сами ищут подобные ошибки, «выполняя код в голове» 40
  • 42. Вторая проблема: мало примеров • Да, можно научить искать некоторые случаи, которые выявляются технологией сопоставления с шаблоном • Но где взять столько примеров? 42
  • 43. Язык C++ быстро меняется. Как искать ошибки в коде, где использован новый синтаксис? 43
  • 44. 44
  • 45. Машинное обучение бесполезно? • Нет, но слишком много «хайпа» • Интересное на мой взгляд направление: фильтрация ложных предупреждений 45
  • 46. Заключение • Статический анализ – это сложно и интересно • Анализаторы сейчас и 10 лет назад – это две большие разницы • Внедрение статического анализа неизбежно из-за роста размеров и сложности проектов • также, как это было с системами контроля версий • также, как это было с багтрекерами 46
  • 47. Ответы на вопросы E-Mail: karpov@viva64.com Twitter: @Code_Analysis Instagram: @pvs_studio_unicorn 47