27
Основы и применение статического анализа кода при разработке ПО Дмитрий Русаков

Основы и применение статического анализа кода при разработке лекция 1

  • Upload
    m2rus

  • View
    65

  • Download
    2

Embed Size (px)

DESCRIPTION

Lection 1 on static analysis

Citation preview

Page 1: Основы и применение статического анализа кода при разработке лекция 1

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

разработке ПО

Дмитрий Русаков

Page 2: Основы и применение статического анализа кода при разработке лекция 1

Когда-то давно

Программист Продукт

Page 3: Основы и применение статического анализа кода при разработке лекция 1

В начале 80-ых

Программист

Продукт

Менеджер

Page 4: Основы и применение статического анализа кода при разработке лекция 1

В начале 90-х

Программист

ПродуктМенеджер

Тестировщик

Page 5: Основы и применение статического анализа кода при разработке лекция 1

Современность

Программист

ПродуктМенеджер

Тестировщик

Page 6: Основы и применение статического анализа кода при разработке лекция 1

Качество ПО

• Каждому требуется своё. ПО, работающее на изолированном компьютере, и веб-сайт правительства

• Целостность• Доступность

• С усложнением инфраструктуры усложнились требования к качеству ПО. Теперь не достаточно выполнять свои функции правильно, необходимо учитывать возможные нападения.

• Принципиальная невозможность добиться абсолютно правильной программы: машина Тьюринга, Microsoft.

• Целостность• Доступность• Конфиденциальность

Page 7: Основы и применение статического анализа кода при разработке лекция 1

Факторы, влияющие на уязвимость ПО

• Ошибки программирования (переполнение буфера),• Ошибки архитектуры (хранение пароля администратора на компьютере пользователя, реализация

контроля доступа на стороне клиента),• Некорректное применение (использование для разграничения доступа программы, в которой нет

аутентификации),• Некорректные настройки (отсутствие запрета модификации настроек безопасности для пользователя),• и т.д.

Page 8: Основы и применение статического анализа кода при разработке лекция 1

Тестирование

• С виду наиболее простой подход.• Позволяет контролировать качество вариантов использования, пришедших в голову тестировщику.• Наиболее проработанный и везде применяемых подход (функциональное тестирование, нагрузочное

тестирование, регрессионное тестирование, Unit Test).• Сложность проведения качественного тестирования

Page 9: Основы и применение статического анализа кода при разработке лекция 1

Ревизия

• Трудоёмкость• Требует определения целей

Page 10: Основы и применение статического анализа кода при разработке лекция 1

Типизированные языки программирования и контроль времени компиляции

• Позволяет выявлять наиболее простые «опечатки» программиста.• Метод быстрой разработки: недостатки.

Page 11: Основы и применение статического анализа кода при разработке лекция 1

Встраивание проверок и ограничений в код, использование "безопасных" функций и языков высокого уровня

• Встраивание проверок и ограничений позволяет выявлять проблемы во время исполнения и реагировать на них (контроль переполнения буфера в Visual С++).

• Использование «безопасных» функций позволяет избежать типичных ошибок программирования• char * strcpy ( char * destination, const char * source );• char * strncpy ( char * destination, const char * source, size_t num );

№3 в Top 25 CWE: «Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')»

• Языки высокого уровня позволяют детальнее продумывать архитектуру, не заботясь о деталях реализации.

Page 12: Основы и применение статического анализа кода при разработке лекция 1

Доказательство правильности свойств программ

• Минус: возможность работы только с небольшими программами• Требуется высокая компетенция экспертов• Формальное доказательство• Model Checking• Pi-calculus

Page 13: Основы и применение статического анализа кода при разработке лекция 1

Статический анализ

• Выявление «нехитрых» ошибок• Значительное количество ложных срабатываний

Page 14: Основы и применение статического анализа кода при разработке лекция 1

Исполнение в виртуальной среде

• Песочницы

Page 15: Основы и применение статического анализа кода при разработке лекция 1

Статический анализ кода

• Анализ, проводимый путём исследования исходных текстов или исполняемых файлов БЕЗ запуска кода.• Автоматическое выявление возможных уязвимостей кода БЕЗ исполнения кода.

• Статический анализ показывает на возможный недочёт.• do {} while true;

• char *p, *k;• p=k;• *k=10;• If ( p ) {};

Page 16: Основы и применение статического анализа кода при разработке лекция 1

Лексический контроль заданных правил

• Фактически – применение регулярных выражений.

• k = j/0;

• i = 0;• …• k = j/i;

• Сообщения компиляторов• Большинство (простейшие) утилиты поиска недостатков кода• Утилиты проверки правил оформления кода

Page 17: Основы и применение статического анализа кода при разработке лекция 1

Анализ программы без учета потока управления

• Прямой обход результатов лексического, синтаксического или семантического разбора.

• i = 0;• …• k = j/i;

• Не используемые переменные, «устаревшие» функции,• Сообщения умных компиляторов• Lint• CppCheck

Page 18: Основы и применение статического анализа кода при разработке лекция 1

Анализ программ с учётом потока управления

• Прямой обход результатов лексического, синтаксического или семантического разбора.

• i = 0;• …• k = j/i;

• Использование переменной до присвоения ей значения, недостижимый код• Klockwork, Coverity, VivaCore• Pvs-studio

Page 19: Основы и применение статического анализа кода при разработке лекция 1

Анализ аннотированного кода

• Аннотирование кода позволяет упростить работу алгоритма

• int readData( __out_bcount_part( maxLength, *length ) void *buffer, const int maxLength, int *length );

• Visual Studio (PreFast)

Page 20: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов PVS-studio

• There are identical sub-expressions 'height <= 0' to the left and to the right of the '||' operator.

• if (width <= 0 || height <= 0 || !data• || INT_MAX/sizeof(uchar *) < uint(height)• || INT_MAX/uint(depth) < uint(width)• || bpl <= 0• || height <= 0• || bpl < min_bytes_per_line• || INT_MAX/uint(bpl) < uint(height))• return d;

• This is a nonsensical comparison: pointer >= 0.• MessageItem *ContextItem::findMessage(const QString &sourcetext, const QString &comment) const• if (c->findMessage(m->text(), m->comment()) >= 0)

Page 21: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов PVS-studio

• The 'throw' operator inside the destructor should be placed within the try..catch block. Raising exception inside the destructor is illegal. • # define QT_RETHROW throw

• QObject::~QObject()• {• if (d->isSignalConnected(0)) {• QT_TRY {• emit destroyed(this);• } QT_CATCH(...) {• // all the signal/slots connections are still in place - if we don't• // quit now, we will crash pretty soon.• qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");• QT_RETHROW;• }• }• }

Page 22: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов PVS-studio

• Pointer to local variable 'tmp' is stored outside the scope of this variable. Such a pointer will become invalid.•

• QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const• {• QList<QGraphicsItem *> tmp;• findVisitor->foundItems = &tmp;• findVisitor->onlyTopLevelItems = onlyTopLevelItems;• climbTree(findVisitor, rect);• // Reset discovery bits.• for (int i = 0; i < tmp.size(); ++i)• tmp.at(i)->d_ptr->itemDiscovered = 0;• return tmp;• }

Page 23: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов PVS-studio

• Pointer to local variable 'tmp' is stored outside the scope of this variable. Such a pointer will become invalid.•

• QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const• {• QList<QGraphicsItem *> tmp;• findVisitor->foundItems = &tmp;• findVisitor->onlyTopLevelItems = onlyTopLevelItems;• climbTree(findVisitor, rect);• // Reset discovery bits.• for (int i = 0; i < tmp.size(); ++i)• tmp.at(i)->d_ptr->itemDiscovered = 0;• return tmp;• }

Page 24: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов CppCheck

• (error) Uninitialized variable: cc

int wfp_dispatch(wfp *p, int cnt, wfp_handler callback, u_char *user){

int cc;if (p->cc == 0) {

cc = p->packet->ulBytesReceived;} else

bp = p->bp;

#define bhp ((wfp_hdr *)bp)ep = bp + cc;

}

Page 25: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов CppCheck

• (error) Uninitialized variable: cc

int wfp_dispatch(wfp *p, int cnt, wfp_handler callback, u_char *user){

int cc;if (p->cc == 0) {

cc = p->packet->ulBytesReceived;} else

bp = p->bp;

#define bhp ((wfp_hdr *)bp)ep = bp + cc;

}

Page 26: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов CppCheck

• (error) Mismatching allocation and deallocation: reason

if (m_minorVerNum >= 8) {StringStorage errorMessage(e.getMessage());size_t reasonLen = errorMessage.getLength();char *reason = new char[reasonLen + 1];try {

if (errorMessage.toAnsiString(reason, reasonLen + 1)) {m_output->writeUInt32(1); m_output->writeUInt32(reasonLen);m_output->writeFully(reason, reasonLen);

}} catch (...) {

delete reason;throw;

}delete reason;

}

Page 27: Основы и применение статического анализа кода при разработке лекция 1

Примеры результатов CppCheck

• (error) Mismatching allocation and deallocation: reason

*/static int file_agent_save_file(FileInfo *file, char *capture_dir){

FILE *fh;fh = fopen(filename, "w");

while (file_mem){

if (!buff || !size )return -1;

}

fclose(fh);return 0;

}