Перейти к содержимому
RAGRAF

CPG-слой: Joern, межпроцедурные вызовы и честная деградация

Что добавляет Joern (php2cpg), 12 фактов CPG, backend torch.sparse, контракт degraded и почему отсутствие Joern — не авария, а режим.

Зачем нужен отдельный слой #

tree-sitter даёт внутрифайловый синтаксис: символы, вызовы в пределах файла, SQL-литералы. Но реальные вопросы агента — межпроцедурные: «что достижимо из этой точки», «обрывается ли маршрут согласования». Для PHP это особенно больно: динамика (call_user_func, магические методы, include-цепочки) делает статическую достижимость нетривиальной. RAGRAF не изобретает анализатор — он подключает Joern (Code Property Graph) как опциональный L1-экстрактор и заворачивает его в свой контракт.

Что именно добавляется #

Этап 5 конвейера (cpg) запускает Joern-сервер (localhost:9500, старт/стоп автоматически) и импортирует в graph.sqlite:

АртефактСодержание
Межпроцедурные CALL-рёбравызовы через границы файлов — то, чего tree-sitter не видит
cfg_edge / dfg_edgeпотоки управления и данных внутри функций (задел под taint-анализ — см. future)
12 фактов CPG-покрытиякакие файлы/функции покрыты CPG, каким парсером (php2cpg), версия слоя
joern_used в ревизии1/0 — флаг, который виден в status и панели; никогда не «подразумевается»

На пилотном корпусе (123 PHP-файла) CPG-этап занял 64 с из 71 с полной индексации — Joern доминирует во времени, поэтому он опционален и отключаем (joern_enabled: false).

slice: единственная CPG-операция #

slice — межпроцедурный срез (вверх/вниз по потокам от символа, глубина настраивается). Это единственная операция, требующая capability=full. Контракт деградации:

Text
$ ragraf -p cfg query slice --name markPaid
exit 3
{"op":"slice","capability":"degraded",
 "reason":"CPG-слой недоступен: Joern не установлен",
 "suggest":"install-joern.ps1 -Download или используйте callers/impact (граф tree-sitter)"}

Отказ с причиной и предложением — вместо пустого результата, который агент принял бы за «зависимостей нет». Это анти-требование №4 в действии.

Алгоритмический backend: torch.sparse #

Обход CPG (достижимость, срезы) реализован в graph_algo.py с тремя бэкендами и честным каскадом:

BackendУсловиеХарактеристика
torch-gputorch + CUDA доступны, граф ≥ порогаCSR-представление на GPU; батч-обходы
torch-cputorch доступентот же код, CPU-тензоры
nonetorch нетчистый Python/SQLite-обход — медленнее, но всегда работает

Выбранный бэкенд пишется в метаданные ревизии (reason-поле), а не подразумевается. Важная честная деталь: CSR-представление ограничивает мутации графа на лету — пересборка CPG идёт полным прогоном (инкрементального CPG в Joern не существует). Порог переключения на тензорный путь — ~5 000 вершин (см. gpu-compute).

Установка и вес #

PowerShell
./scripts/install-joern.ps1 -Download   # скачивает дистрибутив, проверяет SHA-256, восстанавливает окружение при сбое

Требуется JDK 21 + Joern (~5–6 ГБ). Установщик проверяет хеш архива (защита от битых/подменённых загрузок) и восстанавливает прежнее состояние при ошибке — дефекты пайп-дедлока и отсутствия таймаутов закрыты рефакторингом (INSTALLER-REFACTOR-NOTES).

Границы слоя #

  • PHP-first: php2cpg проверен на PHP-корпусах; для других языков CPG экспериментальна (Joern поддерживает многие, но контракт RAGRAF проверен на PHP).
  • Динамика остаётся динамикой: call_user_func-цепочки Joern тоже не раскрывает магически — derived-рёбра с confidence 0.60 и отдельным блоком ответа (см. operations).
  • Taint-анализ не включён: CFG/DFG-факты лежат в графе как задел; продуктовых taint-операций в v0.1.0 нет — это осознанная граница релиза и первая крупная перспектива (future).
  • Зависимости не объявлены в pyproject: torch/Joern — внешние опциональные компоненты; формализация extras (pip install ragraf[gpu]) — пункт R-PKG-1 roadmap.

Смежное: GPU-вычисления → · архитектура → · перспективы →