Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров2.6K

Пролог

В этом тексте я написал про две бесплатные утилиты для статического анализа Си кода: splint и Cpp-Check.

Статический анализатор - это такая консольная программа, которая проверяет Си исходники до компиляции. Своего рода автоматическая инспекция программ.

Суть этой короткой заметки в том, чтобы показать, как просто и лаконично происходит подключение разнообразных статических анализаторов к проекту, который собран скриптами сборки GNU Make.

SP-lint

Существует бесплатный статический анализатор. Называется splint (Secure Programming). Его можно скачать в составе CygWin. Tool(а) находит ошибки в коде. Вся документация 121 стр.

У SpLint много опций настройки. Каждое правило можно либо включать(по умолчанию включено всё) либо отключать(inhibit).

Вот приветствие утилиты:

C:\Users\U>
C:\Users\U>where splint
C:\cygwin64\bin\splint.exe

C:\Users\U>
C:\Users\U>splint
Splint 3.1.2 --- 11 Sep 2013

Source files are .c, .h and .lcl files.  If there is no suffix,
   Splint will look for <file>.c and <file>.lcl.

Use splint -help <topic or flag name> for more information

Topics:
   annotations (describes source-code annotations)
   comments (describes control comments)
   flags (describes flag categories)
   flags <category> (describes flags in category)
   flags all (short description of all flags)
   flags alpha (list all flags alphabetically)
   flags full (full description of all flags)
   mail (information on mailing lists)
   modes (show mode settings)
   parseerrors (help on handling parser errors)
   prefixcodes (character codes in namespace prefixes)
   references (sources for more information)
   vars (environment variables)
   version (information on compilation, maintainer)

C:\Users\U>

Вот скрипт для запуска splint для каждого *.с файла из переменной окружения SOURCES_C

$(info static_analysis_code_base)
MK_PATH_WIN := $(subst /cygdrive/c/,C:/, $(MK_PATH))
ARTEFACTS_DIR=$(MK_PATH_WIN)$(BUILD_DIR)
REPORT_DIR=$(ARTEFACTS_DIR)/static_analysis/

INCDIR := $(subst /cygdrive/c/,C:/, $(INCDIR))
#$(info INCDIR=$(INCDIR))
WORKSPACE_LOC := $(subst /cygdrive/c/,C:/, $(WORKSPACE_LOC))
#$(info WORKSPACE_LOC=$(WORKSPACE_LOC))

STATIC_ANALYSIS_TOOL=splint.exe
SPLINT_OPT += -noeffect
SPLINT_OPT += -retvalbool
SPLINT_OPT += -fullinitblock
SPLINT_OPT += -exportlocal
SPLINT_OPT += -type
SPLINT_OPT += -retvalint
SPLINT_OPT += -paramuse
SPLINT_OPT += -nestcomment
SPLINT_OPT += -nullassign
#$(info SOURCES_C=$(SOURCES_C))

SOURCES_SA := $(subst .c,.sa, $(SOURCES_C))

static_analysis_code_base : $(SOURCES_SA)

%.sa:  %.c
	$(info StaticAnalysisStart)
	$(info ProcFile:$<)
	$(info FileDir:$(dir $<))
	$(info SingleFile:$(notdir $<))
	LOC_DIR_NAME=$(dir $<)
	$(info LocDir:$(LOC_DIR_NAME))
	cd $(dir $<) && pwd && $(STATIC_ANALYSIS_TOOL) -preproc $(SPLINT_OPT)  $(INCDIR) $(OPT) $(notdir $<)

В сущности этот скрипт определяет вот такой конвейер запуска утилит

Что касается впечатлений от использования splint анализатора, то splint мне помог найти использование локальных переменных до их инициализации. Это опция -usedef.

Достоинства splint

1--Splint бесплатный. Скачивается из CygWin

Недостатки splint

1--Иногда не может произвести синтаксический разбор некоторых участков кода.

2--Читает файл только при вызове из корня, где лежит файл. Надо командой cd переходить в папку которая содержит те файлы которые вы хотите проверять splint(ом)

3--Есть ложные срабатывания (Array element xxx[0] used before definition: -usedef)

Cpp-Check

Ещё есть статический анализатор Cpp-Check. Это скрипт для запуска cpp-check. Тут создается отдельная цель сборки специально для статического анализа кодовой базы, которая была избирательно проиндексирована make скриптами.

$(info static_analysis_code_base)
MK_PATH_WIN := $(subst /cygdrive/c/,C:/, $(MK_PATH))
ARTEFACTS_DIR=$(MK_PATH_WIN)$(BUILD_DIR)
REPORT_DIR=$(ARTEFACTS_DIR)/static_analysis/


INCDIR := $(subst /cygdrive/c/,C:/, $(INCDIR))
#$(info INCDIR=$(INCDIR))
$(info WORKSPACE_LOC=$(WORKSPACE_LOC))
WORKSPACE_LOC := $(subst /cygdrive/c/,C:/, $(WORKSPACE_LOC))
$(info WORKSPACE_LOC=$(WORKSPACE_LOC))
#$(error WORKSPACE_LOC=$(WORKSPACE_LOC))

INCDIR += -I$(WORKSPACE_LOC)
    
STATIC_ANALYSIS_TOOL="C:/Program Files/Cppcheck/cppcheck.exe"

#see https://habr.com/ru/articles/210256/
CPP_CHECK_OPT += -q
CPP_CHECK_OPT += --enable=all
CPP_CHECK_OPT += --suppress=sprintfOverlappingData
CPP_CHECK_OPT += --suppress=preprocessorErrorDirective
CPP_CHECK_OPT += --suppress=variableScope
CPP_CHECK_OPT += --suppress=unreadVariable
CPP_CHECK_OPT += --suppress=unmatchedSuppression
CPP_CHECK_OPT += --suppress=missingIncludeSystem
CPP_CHECK_OPT += --suppress=unusedFunction
CPP_CHECK_OPT += --suppress=missingInclude
CPP_CHECK_OPT += --suppress=redundantAssignment
CPP_CHECK_OPT += --suppress=strdupCalled
CPP_CHECK_OPT += --suppress=knownConditionTrueFalse
CPP_CHECK_OPT += --suppress=constParameter

#$(info SOURCES_C=$(SOURCES_C))

SOURCES_SA := $(subst .c,.sa, $(SOURCES_C))

static_analysis_cpp_check: $(SOURCES_SA)

%.sa:  %.c
	cd $(dir $<) && pwd && $(STATIC_ANALYSIS_TOOL) $(CPP_CHECK_OPT) $(INCDIR) $(OPT) $(notdir $<)


Запуск статического анализатора из make скриптов хорош тем, что тут Вы можете через аргументы командной строки утилиты cppcheck отключить проверку конкретных правил.

Итоги

Удалось научиться пользоваться бесплатными статическими анализаторами splint и cppcheck. Ожидания были выше чем результат. Максимум полезного, что находит анализатор splint это использование указателей, которые не были проверены на ноль.

Сppcheck оказался более полезным. CppCheck находит переменные в RAM, которые не меняются в коде.

Как можно заметить, если Вы собираете программу из самостоятельно написанных make скриптов , то Вы можете очень просто интегрировать статический анализ исходников. Буквань добавив 10-30 строчке в общий make скрипт сборки проекта.

В случае же сборки из IDE типа Keil или IAR Вам пришлось бы вручную писать циклопические *.bat скрипты с настройками для статического анализа, прописываю путь к каждому отдельному файлу.

Словарь

Акроним

Расшифровка

SPLint

Secure Programming Lint

IDE

integrated development environment

RAM

random access memory


URLs

Splint Manual

Splint

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

Безопасность встраиваемых систем Linux

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользовались статическим анализатором splint?
8% да2
92% нет23
Проголосовали 25 пользователей. Воздержавшихся нет.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Каким статическим анализатором вы пользовались?
3.13% splint1
40.63% CppCheck13
50% PVS16
0% ldra0
31.25% Clang Static Analyzer10
28.13% другой9
Проголосовали 32 пользователя. Воздержались 11 пользователей.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользовались статическим анализатором CppCheck?
43.75% да14
56.25% нет18
Проголосовали 32 пользователя. Воздержался 1 пользователь.
Теги:
Хабы:
Всего голосов 11: ↑5 и ↓6+2
Комментарии3

Публикации

Работа

Программист С
33 вакансии
DevOps инженер
32 вакансии

Ближайшие события