В данном посте расскажем как анализировать проекты на языке Go, как это работает и как проанализировать проекты с системой сборки Bazel.
Мы поддержали в Svace
сборку проектов для последней версии go 1.20
. Также была поддержана базовая версия сборки проектов на Go для системы Bazel (только для дистрибутивов Linux). Данные изменения будут доступны в ближайшем релизе серии Svace 3.4
.
При сборке проекта с помощью стандартной системы сборки go build
схема использования будет выглядеть следующим образом:
svace init
svace build [команда сборки или скрипт сборки]
На данном этапе будет построено промежуточное представление для всего проекта и его зависимостей. Чтобы запустить анализ, необходимо использовать команду svace analyze
.
Например, пройдем все шаги работы со Svace на проекте Xray-core. На момент написания статьи коммит 46d8bb5
. В данном проекте используется версия go 1.20
.
cd Xray-core
svace init
svace build go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
Получим следующий вывод:
Now Svace will preprocess captured data.
Processing source code markup data...
[**********************************************************************] 100%
Assembled build object: [BUILD]9078355afe76cf71d39d75ae3e47737a240fb4c4
Далее запустим анализ на данном проекте:
svace analyze
По окончании анализа будет выведен список и количество найденных предупреждений:
...
Analysis results:
[BUFFER_OVERFLOW]
DYNAMIC_OVERFLOW: 3
OVERFLOW_UNDER_CHECK: 10
[DEAD_CODE]
REDUNDANT_COMPARISON.ALWAYS_FALSE: 51
UNREACHABLE_CODE: 479
UNREACHABLE_CODE.RET: 29
[DEREF_OF_NULL]
DEREF_AFTER_NULL: 9
DEREF_AFTER_NULL.EX: 22
DEREF_OF_NULL.ASSIGN: 2
DEREF_OF_NULL.COND: 1
...
Total warnings: 4263
...
Далее все предупреждения можно будет увидеть в веб-интерфейсе Svacer.
При сборке с помощью встроенной системы go build
, Svace будет перехватывать вызов исполняемого файла go
. Далее исходя из аргументов go [build/install]
с помощью go list
будут найдены все зависимости для проекта.
В случае сборки с Bazel, внутренний процесс сборки проекта на Go происходит по-другому. Во-первых, Bazel не использует вызов go build
напрямую, а самостоятельно компилирует и линкует проект с помощью go tool [compile/link и т.д.]
команд. Во-вторых, информация о зависимостях передается с помощью правил (go-rules
), а именно go_repository
, которая с помощью go mod download
скачивает исходные коды библиотек во внутреннюю GOPATH
вашего проекта, которую Bazel создает сам. Детальное описание работы сборки Go в Bazel можно посмотреть здесь.
Мы поддержали базовую версию анализа проектов, использующих Bazel, которая также будет доступна в ближайшем релизе серии Svace 3.4
.
Чтобы проанализировать проект, использующий Bazel, предварительно необходимо запустить следующие команды (иначе не все компиляции будут перехвачены):
bazel clean --expunge # для очистки кэша
bazel shutdown # для остановки сервера компиляций bazel
Далее svace build
должен содержать следующий флаг: --enable-ptrace-all
, без него соответствующие команды компиляции go tool [command]
перехвачены не будут.
Если вы хотите проанализировать только Go компиляции, то дополнительно добавьте флаги --disable-language all
, --enable-language go
, благодаря которым будут перехватываться/анализироваться только Go компиляции. Можно использовать как с svace build
, так и с svace analyze
.
Например, команда сборки вашего проекта: bazel build //...
, то svace build
будет выглядеть так:
svace build --disable-language all --enable-language go --enable-ptrace-all bazel build //...
Также для корректной работы Svace
папка проекта .svace-dir
должна быть создана внутри корня анализируемого проекта (актуально только для проектов Bazel).
svace build
будет также работать при использовании bazelisk.
Для примера рассмотрим проект bazel-ethereum. Версия Go в go.mod
: go 1.15
:
cd bazel-go-ethereum
bazel clean --expunge
bazel shutdown
svace init
svace build --enable-ptrace bazelisk build --spawn_strategy=local --define version="local" //...
Запускаем анализ:
svace analyze --disable-language all --enable-language go // т.к. также перехватились C/C++ компиляции
По окончании анализа будет выведен список и количество найденных предупреждений:
...
Goa import time: 6s
Warning suppression...
Suppression time: 684ms
Analysis results:
[BUFFER_OVERFLOW]
DYNAMIC_OVERFLOW: 5
OVERFLOW_UNDER_CHECK: 2
OVERFLOW_UNDER_CHECK.PROC: 1
...
Total warnings: 4415
...
Далее все предупреждения можно будет увидеть в веб-интерфейсе Svacer.
Наш компонент перехвата сборки отслеживает низкоуровневую команду go tool compile
; в режиме модулей, также перехватываются команды go mod download
. Внутри папки .svace-dir/bitcode
создается GOPATH
(.gopath
). Данная GOPATH
будет использована при построении промежуточного представления необходимого для анализа, куда будут скачаны нужные версии зависимостей, заданные для установки с помощью go mod download
через правило go_repository
в таком формате:
https://github.com/bazelbuild/bazel-gazelle/blob/master/repository.md#go_repository
# Download using "go mod download"
go_repository(
name = "com_github_pkg_errors",
importpath = "github.com/pkg/errors",
sum = "h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=",
version = "v0.8.1",
)
В другом случае, будет проанализирована последняя версия зависимости, исходный код которой будет скачан в Svace
.gopath
.