Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.
include не равен зависимости
Почему это важно для SCA/OSA
Соблазн собрать состав C/C++ по #include велик: заголовки лежат в исходниках, их легко грепнуть, и кажется, что #include <openssl/ssl.h> — это и есть зависимость от OpenSSL. Это ложный сигнал в обе стороны. #include означает лишь, что компилятору показали интерфейс; он не говорит ни какая версия используется, ни слинкован ли вообще код этой библиотеки в итоговый бинарь. SCA, построенный на заголовках, систематически ошибается — и пропусками, и ложными срабатываниями.
Эта заметка задаёт базовую дисциплину всего модуля: заголовок — это видимость интерфейса на этапе компиляции, а зависимость — факт линковки кода на этапе сборки. Это разные слои, и состав определяется вторым, а не первым.
Как это проявляется
Расхождение «заголовки против линковки» видно при сопоставлении исходников и реальной команды сборки:
# заголовки, которые видит компилятор
$ grep -rhoE '#include <[^>]+>' src/ | sort -u
#include <nlohmann/json.hpp> # header-only: линковки НЕ будет
#include <openssl/ssl.h> # есть и заголовок, и -lssl
#include <zlib.h> # заголовок есть, а -lz в линковке НЕТ
# что реально передано линкеру
$ grep -oE '\-l[:]?[A-Za-z0-9._+-]+' build.log | sort -u
-lcrypto
-lssl
Здесь три разных случая в одном проекте: nlohmann/json — header-only, кода для линковки нет вообще; OpenSSL — заголовок и -lssl совпали, это настоящая зависимость; zlib — заголовок остался от старого кода, но -lz в линковке нет, то есть фактической зависимости нет (мёртвый include). Список по #include и список по -l не совпали ни в одну сторону.
Ошибка в обе стороны Header-only (Eigen, nlohmann/json, многие Boost): зависимость реальна, но в линковке её нет — состав по
-lеё пропустит, а по#includeпоймает. Мёртвый include: заголовок остался в коде, но соответствующего-lнет — состав по#includeпридумает несуществующую зависимость. Ни один из списков по отдельности не верен.
Слепая зона или приём
Слепая зона — header-only библиотеки: настоящая зависимость, которая не оставляет следа ни в DT_NEEDED, ни в строке линковки, потому что весь её код инлайнится из заголовков в объектные файлы. Поймать её можно только сопоставлением #include с известными header-only библиотеками — ни ldd, ни readelf её не покажут (это смежно со статической линковкой: код вшит, отдельной сущности нет).
Приём — не приравнивать #include к зависимости, а пересекать два независимых источника: заголовки из исходников (через compile_commands.json, см. компиляция и линковка) и реальные строки линковки. Совпадение по обоим — высокий confidence. Только заголовок без -l — либо header-only (реальная зависимость), либо мёртвый include (не зависимость): требует ручного разбора, а не автоматического вывода.
Что делать на проекте
- Не строить состав по
grep #include— это даёт ложные срабатывания (мёртвые include) и пропуски (header-only). - Базой состава делать реальные строки линковки (
-l/-Lизbuild.log), а заголовки использовать как перекрёстную проверку. - Случай «заголовок есть,
-lнет» разбирать вручную: header-only (внести как компонент) или мёртвый include (отбросить). - Вести список известных header-only библиотек проекта — иначе они систематически выпадают из SBOM.
- Заголовок без линковки и без версии в коде заносить в реестр неопознанных, а не игнорировать.
- В отчёте различать уровни доказательства: «совпало заголовок + линковка» и «только заголовок» — это разный confidence записи.
Связь
- Модуль: М09. C/C++ legacy
- Практики: П19. C C++ make build inventory · П20. CMake dependency graph
- Нормативка: ГОСТ Р 56939-2024 · NIST SP 800-218 SSDF (PW.4) · BSI TR-03183-2 v2.1.0
- Смежные заметки 06: компиляция и линковка · статическая линковка · динамическая линковка · vendored source · unresolved libraries