SlideShare a Scribd company logo
ТЕОРИЯ И ПРАКТИКА НАПИСАНИЯ
БЕЗОПАСНОГО КОДА НА C++
ЛАПИЦКИЙ АРТЕМ
LAPITSKY.ARTEM@GMAIL.COM
2
COREHARD // ВВЕДЕНИЕ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ПОЧЕМУ МОЙ КОД МОЖЕТ БЫТЬ НЕБЕЗОПАСНЫМ?
С++ – это конгломерат различных языков
• C, classes, template metaprogramming, preprocessor, STL
• Множество способов решения одной задачи
• Подводные камни на стыке различных подмножеств языка
Высокая ответственность программиста
• Как можно меньше ограничивать разработчика (в том числе и в
возможности выстрелить себе в ногу) – часть философии языка
• В стандарте более двухсот упоминаний ситуаций undefined
behavior и около ста – unspecified behavior
3
COREHARD // ВВЕДЕНИЕ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ПОЧЕМУ МОЙ КОД МОЖЕТ БЫТЬ НЕБЕЗОПАСНЫМ? (2)
Возможности, которые слишком легко использовать неверно
• Адресная арифметика, перегрузка операторов, функции с
переменным числом аргументов, приведение типов в стиле C…
Наследие C
• Синтаксис и философия C;
• Сочетание языка высокого уровня и максимальной
эффективности;
• “You don't pay for what you don't use”;
• Небезопасные функции стандартной библиотеки.
4
COREHARD // ВВЕДЕНИЕ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ЗАЧЕМ ПИСАТЬ БЕЗОПАСНЫЙ КОД?
Ошибки стоят дорого
• 4 июня 1996 года на 39-й секунде полета новейшая беспилотная
ракета-носитель «Ariane 5» взорвалась из-за возникшей ошибки
переполнения целого числа. Стоимость ракеты вместе со
спутниками составила более $8 млрд.
Время стоит дорого
• Отлаживать C/С++ программы – не самое быстрое (и приятное)
занятие;
• Применение практик написания безопасного кода ускоряет
процесс разработки.
5
COREHARD // ВВЕДЕНИЕ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ЗАЧЕМ ПИСАТЬ БЕЗОПАСНЫЙ КОД? (2)
Меньше уязвимостей
• Одна из методик разработки защищенного программного
обеспечения;
• С меньшей вероятностью содержит уязвимости, которые
позволят злоумышленникам совершить недружественные
действия.
Выше надежность
• Обеспечение корректности работы программ;
• Путь к разработке надежного программного обеспечения.
6
Надежное
ПО
Защищенное
ПО
COREHARD // ВВЕДЕНИЕ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ЗАЧЕМ ПИСАТЬ БЕЗОПАСНЫЙ КОД? (3)
Качественное ПО
АСПЕКТЫ БЕЗОПАСНОСТИ КОДА
C++
9
Безопасность границ памяти (bounds safety)
Безопасность времени жизни объектов (lifetime safety)
Безопасность типов (type safety)
Безопасность арифметических операций (arithmetic safety)
Безопасность относительно исключений (exception safety)
Безопасность работы в многопоточной среде (thread safety)
Защищенный код (security)
COREHARD // АСПЕКТЫ БЕЗОПАСНОСТИ КОДА
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
АСПЕКТЫ БЕЗОПАСНОСТИ КОДА
БЕЗОПАСНОСТЬ ГРАНИЦ
ПАМЯТИ
11
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ (BOUNDS SAFETY)
Чтение или запись данных за пределами выделенной области
памяти позволяет очень скоро познакомиться с лучшим
другом C++ разработчика — undefined behavior.
12
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
BUFFER OVERFLOW
Запись в память за пределами выделенного участка (buffer
overflow) может привести к
аварийному завершению приложения с ошибкой сегментации
памяти (SIGSEGV, ACCESS_VIOLATION);
неожиданному поведению из-за модификации данных, не
связанных с выполняемым в данный момент кодом;
порче пользовательских данных;
самому худшему — программа продолжит работать без
обнаруживаемых проблем.
13
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
КАК РОЖДАЮТСЯ ОШИБКИ BUFFER OVERFLOW
Использование адресной арифметики;
Выход за пределы массива;
Использование небезопасных (unchecked) функций работы с
диапазонами данных;
Нарушение правил безопасности типов (type safety).
14
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ИСПОЛЬЗОВАНИЕ АДРЕСНОЙ АРИФМЕТИКИ
struct big{
unsigned long long ull_1; /* typically 8 bytes */
unsigned long long ull_2; /* typically 8 bytes */
unsigned long long ull_3; /* typically 8 bytes */
int si_4; /* typically 4 bytes */
int si_5; /* typically 4 bytes */
};
/* ... */
size_t skip = offsetof(struct big, ull_2);
struct big *s = (struct big *)malloc(sizeof(struct big));
if (!s) {
/* Handle malloc() error */
}
memset(s + skip, 0, sizeof(struct big) - skip);
/* ... */
free(s);
s = NULL;
memset((char *)s + skip, 0, sizeof(struct big) - skip);
15
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ИСПОЛЬЗОВАНИЕ АДРЕСНОЙ АРИФМЕТИКИ (2)
Не используйте адресную арифметику с полиморфным
типами — это undefined behavior! Исключение составляют
только классы со спецификатором final.
Base
Base
Derived Derived a[2]; Base *ptr = &a[0];
++ptr;
16
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ИСПОЛЬЗОВАНИЕ АДРЕСНОЙ АРИФМЕТИКИ (3)
Не всегда интуитивно понятно;
Требует ручной реализации контроля границ буфера;
Нельзя использовать с объектами полиморфных классов;
В целом, хрупкий и ошибкоопасный инструмент языка,
требующий от разработчика предельной осторожности и
внимания;
Использование контейнеров стандартной библиотеки или
обертки над массивом gsl::span – гораздо лучший вариант.
T *ptr; int n;
assert(reinterpret_cast<std::uintptr_t>(ptr + n) == reinterpret_cast<std::uintptr_t>(ptr) + n * sizeof(T));
17
18
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
operator[] стандартных контейнеров C++ не проверяет
границ, а функции std::<container>::at() — проверяют.
int values[10];
values[0] = 1; // OK!
values[-1] = 2; // Undefined behavior
values[10] = 42; // Undefined behavior
std::array<int, 10> values;
values[0] = 1; // OK!
values[11] = 2; // Undefined behavior
values.at(11) = 5; // OK! Throws std::out_of_range
values.at(-1) = 5; // OK! Throws std::out_of_range
ВЫХОД ЗА ПРЕДЕЛЫ МАССИВА
19
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
Всегда следует проверять значение индекса (массива), который был получен
извне (переменные окружения; аргументы функции main; пользовательский
ввод; данные, прочитанные из файла или полученные по сети).
const size_t packet_types_count = 10;
const size_t packet_size[packet_types_count] = {/* ... */};
/* ... */
int32 packet_type = read_packet_type(connection);
if (packet_type >= 0 && packet_type < packet_types_count)
{
size_t size = packet_size[packet_type];
/* ... */
}
else
{
throw InvalidPacket();
}
ВЫХОД ЗА ПРЕДЕЛЫ МАССИВА (2)
20
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
Аналогично, доступ к элементам динамических массивов по индексу требует
проверки индекса относительно размера массива.
void main(int argc, char *argv[])
{
static const int mode_arg_idx = 1;
/*...*/
if (argc > mode_arg_idx)
{
std::string mode_name = argv[mode_arg_idx];
/*...*/
}
/*...*/
}
ВЫХОД ЗА ПРЕДЕЛЫ МАССИВА (3)
21
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
Использование небезопасных (unchecked) функций стандартной
библиотеки повышает шансы возникновения ошибок переполнения
буфера;
Включение в стандарт библиотеки Ranges и STL2 значительно
упростит работу с диапазонами
https://ericniebler.github.io/range-v3/
UNCHECKED ФУНКЦИИ СТАНДАРТНОЙ БИБЛИОТЕКИ
22
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
UNCHECKED ФУНКЦИИ STL
std::vector<int> a, b, c;
// Unchecked output range
std::copy(std::begin(a), std::end(a), std::begin(b));
std::copy_n(std::begin(a), a.size(), std::begin(b));
std::copy_if(std::begin(a), std::end(a), std::begin(b),
[](int value){ return value > 0; });
std::copy_backward(std::begin(a), std::end(a), std::end(b));
std::move(std::begin(a), std::end(a), std::begin(b));
std::move_backward(std::begin(a), std::end(a), std::end(b));
std::set_difference(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c));
std::set_symmetric_difference(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c));
std::set_intersection(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c));
std::set_union(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c));
std::merge(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c));
std::swap_ranges(std::begin(a), std::end(a), std::begin(b));
// Unchecked input range
std::mismatch(std::begin(a), std::end(a), std::begin(b));
std::equal(std::begin(a), std::end(a), std::begin(b));
std::is_permutation(std::begin(a), std::end(a), std::begin(b));
// Checked since C++17
std::mismatch(std::begin(a), std::end(a), std::begin(b), std::end(b));
std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b));
std::is_permutation(std::begin(a), std::end(a), std::begin(b), std::end(b));
23
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
UNCHECKED ФУНКЦИИ STL (2)
Реализовать операции, выполняемые этими функциями всегда
можно безопасным способом:
std::vector<int> a, b;
/* ... */
// Safe #1
if (a.size() <= b.size())
{
std::copy(std::begin(a), std::end(a), std::begin(b));
}
// Safe #2
b.reserve(a.size());
std::copy(std::begin(a), std::end(a), std::back_inserter(b));
// Safe #3
b.insert(std::end(b), std::begin(a), std::end(a));
24
COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
UNCHECKED ФУНКЦИИ СТАНДАРТНОЙ БИБЛИОТЕКИ C
Функция Аналог из STL
std::memset std::fill, std::array<>::fill, {}
std::strcpy, std::strncpy
std::stringstd::strlen
std::strcat, std::strncat
std::memcpy, std::memmove,
std::memcmp
std::array, std::vector
std::gets std::fgets, std::getline
std::sprintf, std::vsprintf,
std::vsnprintf, ...
iostream
std::scanf, std::vfscanf,
std::vfsncanf, ...
std::strtok std::string, std::regex
БЕЗОПАСНОСТЬ ВРЕМЕНИ
ЖИЗНИ ОБЪЕКТОВ
27
COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ (LIFETIME SAFETY)
Чтобы обеспечить безопасность времени жизни объектов
следует
Не использовать объекты до того, как они были успешно
проинициализированы;
Удалять созданные в куче объекты;
Удалять созданные в куче объекты только единожды;
Не использовать объекты после истечения их времени жизни.
28
COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ИСПОЛЬЗУЙТЕ RAII
Всегда отдавайте предпочтение использование идиомы RAII ручному
управлению ресурсами.
// Manual resource management
Foo *bar = new Foo();
/*...*/
delete bar;
Foo *lots_of_bars = new Foo[100];
/*...*/
delete []lots_of_bars;
// RAII way
std::unique_ptr<Foo> bar = std::make_unique<Foo>();
std::vector<Foo> lots_of_bars(100);
29
COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
НЕ СОЗДАВАЙТЕ ВИСЯЧИЕ ССЫЛКИ
Не выносите ссылки на локальные/временные объекты за пределы их
области видимости.
// returned reference is dangling
const std::string& get_value()
{
std::string value;
/* ... */
return value;
}
// str is dangling
const char *str;
{
std::string value;
/* ... */
str = value.c_str();
}
// captured reference is dangling
std::function<void()> f;
{
std::string value;
/* ... */
f = [&]() {
std::cout << value;
};
}
30
COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
НЕ СОЗДАВАЙТЕ ВИСЯЧИЕ ССЫЛКИ (2)
Будьте осторожны с функциями, которые возвращают ссылки или прокси-
объекты.
// r, max_str, min_str are dangling
const std::string& max_str = std::max("hello"s, "world"s);
const std::string& min_str = std::min("hello"s, "world"s);
const int& r = std::clamp(-1, 0, 255);
// beware of std::vector<bool>
std::vector<bool> some_bools{ /* ... */ };
auto first_bool = some_bools[0];
some_bools.clear();
// first_bool is invalid
31
COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
УЧИТЫВАЙТЕ ВОЗМОЖНОСТЬ ИНВАЛИДАЦИИ ИТЕРАТОРОВ
Модификация контейнеров может привести к инвалидации итераторов,
которые были созданы ранее. Невалидный итератор — это также
разновидность висячей ссылки.
std::vector<int> numbers{ 0, 1, 2, 3, 4 };
auto number_it = numbers.begin();
numbers.push_back(5); // probably involves memory reallocation
//number_it may be invalid
БЕЗОПАСНОСТЬ ТИПОВ
34
COREHARD // БЕЗОПАСНОСТЬ ТИПОВ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
БЕЗОПАСНОСТЬ ТИПОВ (TYPE SAFETY)
Не использовать reinterpret_cast (в том числе через union);
Отказаться от static_cast для приведения вниз по иерархии
(downcast);
Не использовать понапрасну const_cast;
Не использовать приведение типов в стиле C;
Вместо union использовать variant (например,
boost::variant);
Вместо функций с переменным числом аргументов использовать
(varargs) использовать variadic templates;
Соблюдать One Definition Rule.
35
COREHARD // БЕЗОПАСНОСТЬ ТИПОВ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ИСПОЛЬЗОВАНИЕ REINTERPRET_CAST
Оператор позволяет убедить компилятор
интерпретировать биты объекта одного
типа как объект другого типа, никак с
первым типом не связанного;
В общем случае гарантии корректности
такого преобразования отсутствуют;
Подталкивает к тому, чтобы делать предположения о способе
представления данных в памяти, что само по себе ненадежно и
ведет к написанию некроссплатформенного кода;
Нельзя использовать для приведения полиморфных типов,
поскольку reinterpret_cast никак не учитывает особенности
размещения таких объектов;
36
COREHARD // БЕЗОПАСНОСТЬ ТИПОВ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ИСПОЛЬЗОВАНИЕ CONST_CAST
Позволяет избавиться от спецификаторов const и volatile;
Добавляет неожиданные для разработчика side-эффекты;
В случае если полученная после преобразования non-const ссылка
связана с настоящей константой, ее модификация приведет к undefined
behavior;
Компилятор неявно выполняет const_cast для строковых литералов (к
char*), так как это необходимо для работы с функциями стандартной
библиотеки C. Но это не значит, что строковые литералы можно
модифицировать!;
Использование оправдано только при работе с библиотеками C и API,
которые не использует спецификатор const при отсутствии side-
эффектов.
37
COREHARD // ПРОФИЛИ БЕЗОПАСНОГО КОДА
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ИСПОЛЬЗОВАНИЕ C-STYLE CAST
Производит одно из следующих преобразований:
const_cast
static_cast
static_cast + const_cast
reinterpret_cast
reinterpret_cast + const_cast
Нет возможности узнать, какое именно преобразование произошло или
как-то повлиять на этот выбор;
Поведение может быть разным при одних и тех же преобразованиях в
зависимости от наличия/отсутствия определения преобразуемых типов.
38
COREHARD // БЕЗОПАСНОСТЬ ТИПОВ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
СОБЛЮДАЙТЕ ONE DEFINITION RULE
Нарушение ODR – undefined behavior. Ошибки, связанные с нарушением ODR
сложно диагностировать.
#pragma once
class Foo
{
/* ... */
private:
int a1;
#ifdef ENABLE_SUPER_FEATURE
int a2;
int a3;
#endif
};
#define ENABLE_SUPER_FEATURE
/* ... */
#include "Foo.h"
size_t GetFooSize1()
{
return sizeof(Foo);
}
// returns 12
Foo.h GetFooSize1.cpp GetFooSize2.cpp
/* ... */
#include "Foo.h"
size_t GetFooSize2()
{
return sizeof(Foo);
}
// returns 4
БЕЗОПАСНОСТЬ
АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ
41
COREHARD // БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ
Необходимо учитывать возможность «unsigned integer
wrapping» при совершении арифметических операций;
Перед выполнением арифметических операций с целыми
числами стоит удостовериться в том, что не произойдет
переполнение. Переполнение знакового целого — undefined
behavior;
Результат операции целочисленного деления на 0 (или взятие
остатка от деления на 0) не определен;
0 программистов ругал сердитый шеф,
Потом уволил одного, и стало их FF.
(с) Компьютерра
42
COREHARD // БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ (2)
int a = std::numeric_limits<int>::max();
int b;
b = a + 1; // Undefined behavior
b = -a; // OK!
/* int: –2,147,483,648 .. 2,147,483,647 */
b = a / 0; // Undefined behavior
b = a % 0; // Undefined behavior
a = std::numeric_limits<int>::min();
b = a - 1; // Undefined behavior
b = -a; // Undefined behavior
unsigned int c = std::numeric_limits<unsigned int>::max();
++c; // OK! Wrapping around
assert(c == std::numeric_limits<unsigned int>::min());
assert(c == 0);
--c; // OK! Wrapping around
assert(c == std::numeric_limits<unsigned int>::max());
УЯЗВИМОСТИ В ПРОГРАММНОМ
ОБЕСПЕЧЕНИИ
45
COREHARD // УЯЗВИМОСТИ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
CWE/SANS TOP 25 MOST DANGEROUS SOFTWARE ERRORS
Rank Name
[3] Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
[18] Use of Potentially Dangerous Function
[20] Incorrect Calculation of Buffer Size
[23] Uncontrolled Format String
[24] Integer Overflow or Wraparound
Top 25 Most Dangerous Software Errors – результат работы экспертов в
области безопасности ПО из SANS Institute и MITRE.
46
COREHARD // ИНФОРМАЦИЯ ДЛЯ ИЗУЧЕНИЯ
ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016
ЧТО ПОЧИТАТЬ?
С++ Core Guidelines
http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
SEI CERT C++ Coding Standard
https://www.securecoding.cert.org/
OWASP C/C++ Technology Initiative
https://www.owasp.org/index.php/C%2B%2B
Common Weakness Enumeration by MITRE Corporation
http://cwe.mitre.org/
ЛАПИЦКИЙ АРТЕМ
Software Developer https://www.facebook.com/WargamingMinsk
ВОПРОСЫ?
lapitsky.artem@gmail.com
wargaming.com
https://www.linkedin.com/company/wargaming-net
СПАСИБО ЗА ВНИМАНИЕ!

More Related Content

Viewers also liked

Антон Полухин. C++17
Антон Полухин. C++17Антон Полухин. C++17
Антон Полухин. C++17
Sergey Platonov
 
Clang tidy
Clang tidyClang tidy
Clang tidy
Yury Yafimachau
 
Parallel STL
Parallel STLParallel STL
Parallel STL
Evgeny Krutko
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
Platonov Sergey
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines
Sergey Zubkov
 
Quality assurance of large c++ projects
Quality assurance of large c++ projectsQuality assurance of large c++ projects
Quality assurance of large c++ projects
corehard_by
 

Viewers also liked (6)

Антон Полухин. C++17
Антон Полухин. C++17Антон Полухин. C++17
Антон Полухин. C++17
 
Clang tidy
Clang tidyClang tidy
Clang tidy
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines
 
Quality assurance of large c++ projects
Quality assurance of large c++ projectsQuality assurance of large c++ projects
Quality assurance of large c++ projects
 

Similar to Теория и практика написания безопасного кода на C++

использование систем аналитики крэшей
использование систем аналитики крэшейиспользование систем аналитики крэшей
использование систем аналитики крэшей
corehard_by
 
Переполнение буфера и другие уязвимости ПО - Роман Олейников
Переполнение буфера и другие уязвимости ПО - Роман ОлейниковПереполнение буфера и другие уязвимости ПО - Роман Олейников
Переполнение буфера и другие уязвимости ПО - Роман Олейников
HackIT Ukraine
 
Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...
Roman Oliynykov
 
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ... Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
Yandex
 
Перехват беспроводных гаджетов — от квадрокоптеров до мышек
Перехват беспроводных гаджетов — от квадрокоптеров до мышекПерехват беспроводных гаджетов — от квадрокоптеров до мышек
Перехват беспроводных гаджетов — от квадрокоптеров до мышек
Positive Hack Days
 
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптах
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптахПриемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптах
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптах
revisium
 
06. Память Cortex-M3(4)
06. Память Cortex-M3(4)06. Память Cortex-M3(4)
06. Память Cortex-M3(4)
KamlachPV
 
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценариях
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценарияхПриемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценариях
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценарияхPositive Hack Days
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9Technopark
 
Mixing c++ and python
Mixing c++ and pythonMixing c++ and python
Mixing c++ and python
corehard_by
 
static - defcon russia 20
static  - defcon russia 20static  - defcon russia 20
static - defcon russia 20
DefconRussia
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Platonov Sergey
 
Михаил Белопухов: OpenBSD: Куда катится крипто?
Михаил Белопухов: OpenBSD: Куда катится крипто?Михаил Белопухов: OpenBSD: Куда катится крипто?
Михаил Белопухов: OpenBSD: Куда катится крипто?
Yandex
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибки
Platonov Sergey
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибки
Andrey Karpov
 
Универсальный сигнатурный анализ кода на C#, Java, PHP
Универсальный сигнатурный анализ кода на C#, Java, PHPУниверсальный сигнатурный анализ кода на C#, Java, PHP
Универсальный сигнатурный анализ кода на C#, Java, PHP
Иван Кочуркин
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
Andrey Karpov
 
Поиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кодаПоиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кода
corehard_by
 
Поиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кодаПоиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кода
Andrey Karpov
 

Similar to Теория и практика написания безопасного кода на C++ (20)

использование систем аналитики крэшей
использование систем аналитики крэшейиспользование систем аналитики крэшей
использование систем аналитики крэшей
 
Переполнение буфера и другие уязвимости ПО - Роман Олейников
Переполнение буфера и другие уязвимости ПО - Роман ОлейниковПереполнение буфера и другие уязвимости ПО - Роман Олейников
Переполнение буфера и другие уязвимости ПО - Роман Олейников
 
Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...
 
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ... Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 
Перехват беспроводных гаджетов — от квадрокоптеров до мышек
Перехват беспроводных гаджетов — от квадрокоптеров до мышекПерехват беспроводных гаджетов — от квадрокоптеров до мышек
Перехват беспроводных гаджетов — от квадрокоптеров до мышек
 
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптах
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптахПриемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптах
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP скриптах
 
06. Память Cortex-M3(4)
06. Память Cortex-M3(4)06. Память Cortex-M3(4)
06. Память Cortex-M3(4)
 
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценариях
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценарияхПриемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценариях
Приемы, затрудняющие обнаружение и анализ вредоносного кода в PHP-сценариях
 
C++ осень 2012 лекция 9
C++ осень 2012 лекция 9C++ осень 2012 лекция 9
C++ осень 2012 лекция 9
 
Mixing c++ and python
Mixing c++ and pythonMixing c++ and python
Mixing c++ and python
 
static - defcon russia 20
static  - defcon russia 20static  - defcon russia 20
static - defcon russia 20
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведенияДракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
 
Михаил Белопухов: OpenBSD: Куда катится крипто?
Михаил Белопухов: OpenBSD: Куда катится крипто?Михаил Белопухов: OpenBSD: Куда катится крипто?
Михаил Белопухов: OpenBSD: Куда катится крипто?
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибки
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибки
 
Универсальный сигнатурный анализ кода на C#, Java, PHP
Универсальный сигнатурный анализ кода на C#, Java, PHPУниверсальный сигнатурный анализ кода на C#, Java, PHP
Универсальный сигнатурный анализ кода на C#, Java, PHP
 
Bytecode
BytecodeBytecode
Bytecode
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Поиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кодаПоиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кода
 
Поиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кодаПоиск уязвимостей с использованием статического анализа кода
Поиск уязвимостей с использованием статического анализа кода
 

More from corehard_by

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
corehard_by
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
corehard_by
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
corehard_by
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
corehard_by
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
corehard_by
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
corehard_by
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
corehard_by
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
corehard_by
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
corehard_by
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
corehard_by
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
corehard_by
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
corehard_by
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
corehard_by
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
corehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
corehard_by
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
corehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
corehard_by
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
corehard_by
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
corehard_by
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последстви...
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 

Теория и практика написания безопасного кода на C++

  • 1. ТЕОРИЯ И ПРАКТИКА НАПИСАНИЯ БЕЗОПАСНОГО КОДА НА C++ ЛАПИЦКИЙ АРТЕМ LAPITSKY.ARTEM@GMAIL.COM
  • 2.
  • 3. 2 COREHARD // ВВЕДЕНИЕ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ПОЧЕМУ МОЙ КОД МОЖЕТ БЫТЬ НЕБЕЗОПАСНЫМ? С++ – это конгломерат различных языков • C, classes, template metaprogramming, preprocessor, STL • Множество способов решения одной задачи • Подводные камни на стыке различных подмножеств языка Высокая ответственность программиста • Как можно меньше ограничивать разработчика (в том числе и в возможности выстрелить себе в ногу) – часть философии языка • В стандарте более двухсот упоминаний ситуаций undefined behavior и около ста – unspecified behavior
  • 4. 3 COREHARD // ВВЕДЕНИЕ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ПОЧЕМУ МОЙ КОД МОЖЕТ БЫТЬ НЕБЕЗОПАСНЫМ? (2) Возможности, которые слишком легко использовать неверно • Адресная арифметика, перегрузка операторов, функции с переменным числом аргументов, приведение типов в стиле C… Наследие C • Синтаксис и философия C; • Сочетание языка высокого уровня и максимальной эффективности; • “You don't pay for what you don't use”; • Небезопасные функции стандартной библиотеки.
  • 5. 4 COREHARD // ВВЕДЕНИЕ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ЗАЧЕМ ПИСАТЬ БЕЗОПАСНЫЙ КОД? Ошибки стоят дорого • 4 июня 1996 года на 39-й секунде полета новейшая беспилотная ракета-носитель «Ariane 5» взорвалась из-за возникшей ошибки переполнения целого числа. Стоимость ракеты вместе со спутниками составила более $8 млрд. Время стоит дорого • Отлаживать C/С++ программы – не самое быстрое (и приятное) занятие; • Применение практик написания безопасного кода ускоряет процесс разработки.
  • 6. 5 COREHARD // ВВЕДЕНИЕ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ЗАЧЕМ ПИСАТЬ БЕЗОПАСНЫЙ КОД? (2) Меньше уязвимостей • Одна из методик разработки защищенного программного обеспечения; • С меньшей вероятностью содержит уязвимости, которые позволят злоумышленникам совершить недружественные действия. Выше надежность • Обеспечение корректности работы программ; • Путь к разработке надежного программного обеспечения.
  • 7. 6 Надежное ПО Защищенное ПО COREHARD // ВВЕДЕНИЕ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ЗАЧЕМ ПИСАТЬ БЕЗОПАСНЫЙ КОД? (3) Качественное ПО
  • 8.
  • 10. 9 Безопасность границ памяти (bounds safety) Безопасность времени жизни объектов (lifetime safety) Безопасность типов (type safety) Безопасность арифметических операций (arithmetic safety) Безопасность относительно исключений (exception safety) Безопасность работы в многопоточной среде (thread safety) Защищенный код (security) COREHARD // АСПЕКТЫ БЕЗОПАСНОСТИ КОДА ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 АСПЕКТЫ БЕЗОПАСНОСТИ КОДА
  • 12. 11 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ (BOUNDS SAFETY) Чтение или запись данных за пределами выделенной области памяти позволяет очень скоро познакомиться с лучшим другом C++ разработчика — undefined behavior.
  • 13. 12 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 BUFFER OVERFLOW Запись в память за пределами выделенного участка (buffer overflow) может привести к аварийному завершению приложения с ошибкой сегментации памяти (SIGSEGV, ACCESS_VIOLATION); неожиданному поведению из-за модификации данных, не связанных с выполняемым в данный момент кодом; порче пользовательских данных; самому худшему — программа продолжит работать без обнаруживаемых проблем.
  • 14. 13 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 КАК РОЖДАЮТСЯ ОШИБКИ BUFFER OVERFLOW Использование адресной арифметики; Выход за пределы массива; Использование небезопасных (unchecked) функций работы с диапазонами данных; Нарушение правил безопасности типов (type safety).
  • 15. 14 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ИСПОЛЬЗОВАНИЕ АДРЕСНОЙ АРИФМЕТИКИ struct big{ unsigned long long ull_1; /* typically 8 bytes */ unsigned long long ull_2; /* typically 8 bytes */ unsigned long long ull_3; /* typically 8 bytes */ int si_4; /* typically 4 bytes */ int si_5; /* typically 4 bytes */ }; /* ... */ size_t skip = offsetof(struct big, ull_2); struct big *s = (struct big *)malloc(sizeof(struct big)); if (!s) { /* Handle malloc() error */ } memset(s + skip, 0, sizeof(struct big) - skip); /* ... */ free(s); s = NULL; memset((char *)s + skip, 0, sizeof(struct big) - skip);
  • 16. 15 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ИСПОЛЬЗОВАНИЕ АДРЕСНОЙ АРИФМЕТИКИ (2) Не используйте адресную арифметику с полиморфным типами — это undefined behavior! Исключение составляют только классы со спецификатором final. Base Base Derived Derived a[2]; Base *ptr = &a[0]; ++ptr;
  • 17. 16 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ИСПОЛЬЗОВАНИЕ АДРЕСНОЙ АРИФМЕТИКИ (3) Не всегда интуитивно понятно; Требует ручной реализации контроля границ буфера; Нельзя использовать с объектами полиморфных классов; В целом, хрупкий и ошибкоопасный инструмент языка, требующий от разработчика предельной осторожности и внимания; Использование контейнеров стандартной библиотеки или обертки над массивом gsl::span – гораздо лучший вариант. T *ptr; int n; assert(reinterpret_cast<std::uintptr_t>(ptr + n) == reinterpret_cast<std::uintptr_t>(ptr) + n * sizeof(T));
  • 18. 17
  • 19. 18 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 operator[] стандартных контейнеров C++ не проверяет границ, а функции std::<container>::at() — проверяют. int values[10]; values[0] = 1; // OK! values[-1] = 2; // Undefined behavior values[10] = 42; // Undefined behavior std::array<int, 10> values; values[0] = 1; // OK! values[11] = 2; // Undefined behavior values.at(11) = 5; // OK! Throws std::out_of_range values.at(-1) = 5; // OK! Throws std::out_of_range ВЫХОД ЗА ПРЕДЕЛЫ МАССИВА
  • 20. 19 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 Всегда следует проверять значение индекса (массива), который был получен извне (переменные окружения; аргументы функции main; пользовательский ввод; данные, прочитанные из файла или полученные по сети). const size_t packet_types_count = 10; const size_t packet_size[packet_types_count] = {/* ... */}; /* ... */ int32 packet_type = read_packet_type(connection); if (packet_type >= 0 && packet_type < packet_types_count) { size_t size = packet_size[packet_type]; /* ... */ } else { throw InvalidPacket(); } ВЫХОД ЗА ПРЕДЕЛЫ МАССИВА (2)
  • 21. 20 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 Аналогично, доступ к элементам динамических массивов по индексу требует проверки индекса относительно размера массива. void main(int argc, char *argv[]) { static const int mode_arg_idx = 1; /*...*/ if (argc > mode_arg_idx) { std::string mode_name = argv[mode_arg_idx]; /*...*/ } /*...*/ } ВЫХОД ЗА ПРЕДЕЛЫ МАССИВА (3)
  • 22. 21 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 Использование небезопасных (unchecked) функций стандартной библиотеки повышает шансы возникновения ошибок переполнения буфера; Включение в стандарт библиотеки Ranges и STL2 значительно упростит работу с диапазонами https://ericniebler.github.io/range-v3/ UNCHECKED ФУНКЦИИ СТАНДАРТНОЙ БИБЛИОТЕКИ
  • 23. 22 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 UNCHECKED ФУНКЦИИ STL std::vector<int> a, b, c; // Unchecked output range std::copy(std::begin(a), std::end(a), std::begin(b)); std::copy_n(std::begin(a), a.size(), std::begin(b)); std::copy_if(std::begin(a), std::end(a), std::begin(b), [](int value){ return value > 0; }); std::copy_backward(std::begin(a), std::end(a), std::end(b)); std::move(std::begin(a), std::end(a), std::begin(b)); std::move_backward(std::begin(a), std::end(a), std::end(b)); std::set_difference(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c)); std::set_symmetric_difference(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c)); std::set_intersection(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c)); std::set_union(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c)); std::merge(std::begin(a), std::end(a), std::begin(b), std::end(b), std::begin(c)); std::swap_ranges(std::begin(a), std::end(a), std::begin(b)); // Unchecked input range std::mismatch(std::begin(a), std::end(a), std::begin(b)); std::equal(std::begin(a), std::end(a), std::begin(b)); std::is_permutation(std::begin(a), std::end(a), std::begin(b)); // Checked since C++17 std::mismatch(std::begin(a), std::end(a), std::begin(b), std::end(b)); std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b)); std::is_permutation(std::begin(a), std::end(a), std::begin(b), std::end(b));
  • 24. 23 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 UNCHECKED ФУНКЦИИ STL (2) Реализовать операции, выполняемые этими функциями всегда можно безопасным способом: std::vector<int> a, b; /* ... */ // Safe #1 if (a.size() <= b.size()) { std::copy(std::begin(a), std::end(a), std::begin(b)); } // Safe #2 b.reserve(a.size()); std::copy(std::begin(a), std::end(a), std::back_inserter(b)); // Safe #3 b.insert(std::end(b), std::begin(a), std::end(a));
  • 25. 24 COREHARD // БЕЗОПАСНОСТЬ ГРАНИЦ ПАМЯТИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 UNCHECKED ФУНКЦИИ СТАНДАРТНОЙ БИБЛИОТЕКИ C Функция Аналог из STL std::memset std::fill, std::array<>::fill, {} std::strcpy, std::strncpy std::stringstd::strlen std::strcat, std::strncat std::memcpy, std::memmove, std::memcmp std::array, std::vector std::gets std::fgets, std::getline std::sprintf, std::vsprintf, std::vsnprintf, ... iostream std::scanf, std::vfscanf, std::vfsncanf, ... std::strtok std::string, std::regex
  • 27.
  • 28. 27 COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ (LIFETIME SAFETY) Чтобы обеспечить безопасность времени жизни объектов следует Не использовать объекты до того, как они были успешно проинициализированы; Удалять созданные в куче объекты; Удалять созданные в куче объекты только единожды; Не использовать объекты после истечения их времени жизни.
  • 29. 28 COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ИСПОЛЬЗУЙТЕ RAII Всегда отдавайте предпочтение использование идиомы RAII ручному управлению ресурсами. // Manual resource management Foo *bar = new Foo(); /*...*/ delete bar; Foo *lots_of_bars = new Foo[100]; /*...*/ delete []lots_of_bars; // RAII way std::unique_ptr<Foo> bar = std::make_unique<Foo>(); std::vector<Foo> lots_of_bars(100);
  • 30. 29 COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 НЕ СОЗДАВАЙТЕ ВИСЯЧИЕ ССЫЛКИ Не выносите ссылки на локальные/временные объекты за пределы их области видимости. // returned reference is dangling const std::string& get_value() { std::string value; /* ... */ return value; } // str is dangling const char *str; { std::string value; /* ... */ str = value.c_str(); } // captured reference is dangling std::function<void()> f; { std::string value; /* ... */ f = [&]() { std::cout << value; }; }
  • 31. 30 COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 НЕ СОЗДАВАЙТЕ ВИСЯЧИЕ ССЫЛКИ (2) Будьте осторожны с функциями, которые возвращают ссылки или прокси- объекты. // r, max_str, min_str are dangling const std::string& max_str = std::max("hello"s, "world"s); const std::string& min_str = std::min("hello"s, "world"s); const int& r = std::clamp(-1, 0, 255); // beware of std::vector<bool> std::vector<bool> some_bools{ /* ... */ }; auto first_bool = some_bools[0]; some_bools.clear(); // first_bool is invalid
  • 32. 31 COREHARD // БЕЗОПАСНОСТЬ ВРЕМЕНИ ЖИЗНИ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 УЧИТЫВАЙТЕ ВОЗМОЖНОСТЬ ИНВАЛИДАЦИИ ИТЕРАТОРОВ Модификация контейнеров может привести к инвалидации итераторов, которые были созданы ранее. Невалидный итератор — это также разновидность висячей ссылки. std::vector<int> numbers{ 0, 1, 2, 3, 4 }; auto number_it = numbers.begin(); numbers.push_back(5); // probably involves memory reallocation //number_it may be invalid
  • 34.
  • 35. 34 COREHARD // БЕЗОПАСНОСТЬ ТИПОВ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 БЕЗОПАСНОСТЬ ТИПОВ (TYPE SAFETY) Не использовать reinterpret_cast (в том числе через union); Отказаться от static_cast для приведения вниз по иерархии (downcast); Не использовать понапрасну const_cast; Не использовать приведение типов в стиле C; Вместо union использовать variant (например, boost::variant); Вместо функций с переменным числом аргументов использовать (varargs) использовать variadic templates; Соблюдать One Definition Rule.
  • 36. 35 COREHARD // БЕЗОПАСНОСТЬ ТИПОВ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ИСПОЛЬЗОВАНИЕ REINTERPRET_CAST Оператор позволяет убедить компилятор интерпретировать биты объекта одного типа как объект другого типа, никак с первым типом не связанного; В общем случае гарантии корректности такого преобразования отсутствуют; Подталкивает к тому, чтобы делать предположения о способе представления данных в памяти, что само по себе ненадежно и ведет к написанию некроссплатформенного кода; Нельзя использовать для приведения полиморфных типов, поскольку reinterpret_cast никак не учитывает особенности размещения таких объектов;
  • 37. 36 COREHARD // БЕЗОПАСНОСТЬ ТИПОВ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ИСПОЛЬЗОВАНИЕ CONST_CAST Позволяет избавиться от спецификаторов const и volatile; Добавляет неожиданные для разработчика side-эффекты; В случае если полученная после преобразования non-const ссылка связана с настоящей константой, ее модификация приведет к undefined behavior; Компилятор неявно выполняет const_cast для строковых литералов (к char*), так как это необходимо для работы с функциями стандартной библиотеки C. Но это не значит, что строковые литералы можно модифицировать!; Использование оправдано только при работе с библиотеками C и API, которые не использует спецификатор const при отсутствии side- эффектов.
  • 38. 37 COREHARD // ПРОФИЛИ БЕЗОПАСНОГО КОДА ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ИСПОЛЬЗОВАНИЕ C-STYLE CAST Производит одно из следующих преобразований: const_cast static_cast static_cast + const_cast reinterpret_cast reinterpret_cast + const_cast Нет возможности узнать, какое именно преобразование произошло или как-то повлиять на этот выбор; Поведение может быть разным при одних и тех же преобразованиях в зависимости от наличия/отсутствия определения преобразуемых типов.
  • 39. 38 COREHARD // БЕЗОПАСНОСТЬ ТИПОВ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 СОБЛЮДАЙТЕ ONE DEFINITION RULE Нарушение ODR – undefined behavior. Ошибки, связанные с нарушением ODR сложно диагностировать. #pragma once class Foo { /* ... */ private: int a1; #ifdef ENABLE_SUPER_FEATURE int a2; int a3; #endif }; #define ENABLE_SUPER_FEATURE /* ... */ #include "Foo.h" size_t GetFooSize1() { return sizeof(Foo); } // returns 12 Foo.h GetFooSize1.cpp GetFooSize2.cpp /* ... */ #include "Foo.h" size_t GetFooSize2() { return sizeof(Foo); } // returns 4
  • 41.
  • 42. 41 COREHARD // БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ Необходимо учитывать возможность «unsigned integer wrapping» при совершении арифметических операций; Перед выполнением арифметических операций с целыми числами стоит удостовериться в том, что не произойдет переполнение. Переполнение знакового целого — undefined behavior; Результат операции целочисленного деления на 0 (или взятие остатка от деления на 0) не определен; 0 программистов ругал сердитый шеф, Потом уволил одного, и стало их FF. (с) Компьютерра
  • 43. 42 COREHARD // БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 БЕЗОПАСНОСТЬ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ (2) int a = std::numeric_limits<int>::max(); int b; b = a + 1; // Undefined behavior b = -a; // OK! /* int: –2,147,483,648 .. 2,147,483,647 */ b = a / 0; // Undefined behavior b = a % 0; // Undefined behavior a = std::numeric_limits<int>::min(); b = a - 1; // Undefined behavior b = -a; // Undefined behavior unsigned int c = std::numeric_limits<unsigned int>::max(); ++c; // OK! Wrapping around assert(c == std::numeric_limits<unsigned int>::min()); assert(c == 0); --c; // OK! Wrapping around assert(c == std::numeric_limits<unsigned int>::max());
  • 45.
  • 46. 45 COREHARD // УЯЗВИМОСТИ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 CWE/SANS TOP 25 MOST DANGEROUS SOFTWARE ERRORS Rank Name [3] Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') [18] Use of Potentially Dangerous Function [20] Incorrect Calculation of Buffer Size [23] Uncontrolled Format String [24] Integer Overflow or Wraparound Top 25 Most Dangerous Software Errors – результат работы экспертов в области безопасности ПО из SANS Institute и MITRE.
  • 47. 46 COREHARD // ИНФОРМАЦИЯ ДЛЯ ИЗУЧЕНИЯ ЛАПИЦКИЙ АРТЁМ // COREHARD // 18.06.2016 ЧТО ПОЧИТАТЬ? С++ Core Guidelines http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines SEI CERT C++ Coding Standard https://www.securecoding.cert.org/ OWASP C/C++ Technology Initiative https://www.owasp.org/index.php/C%2B%2B Common Weakness Enumeration by MITRE Corporation http://cwe.mitre.org/
  • 48. ЛАПИЦКИЙ АРТЕМ Software Developer https://www.facebook.com/WargamingMinsk ВОПРОСЫ? lapitsky.artem@gmail.com wargaming.com https://www.linkedin.com/company/wargaming-net