Page 126 - 《软件学报》2026年第7期
P. 126

徐美秋 等: CAnalyzer: 面向  C/C++源代码的软件成分分析技术                                         2811


                 成分, 为开发者理解和分析软件组成提供了可靠的支持.
                    (3) 精准而完整的    TPL  依赖关系建模. CAnalyzer 通过分析源码文件中“#include”“extern”等指令以及标识符建
                 立  TPL  间的依赖关系图. 该依赖关系图详细展示了软件项目中各个组件之间的依赖关系, 为安全漏洞传播和软件
                 许可证合规性分析提供数据支持.
                    (4) OpenHarmony  社区认可的软件成分分析技术. CAnalyzer 已协助        OpenHarmony  社区中  689  个  C/C++代码
                 仓库识别出     166  个外部  C/C++ TPL  成分, 其中  61  个获得开发者确认, 为首次标注. 结合          C/C++漏洞数据库,
                 CAnalyzer 检测出  10  个同源安全漏洞, 其中    3  个已被社区安全响应工作组确认, 为有效漏洞. 因为本文提出的软件
                 成分分析技术对      OpenHarmony 社区安全治理方面的贡献, 作者团队被          OpenHarmony 安全委员会授予“OpenHarmony
                 社区安全治理示范单位”. CAnalyzer 开源仓库地址: https://gitcode.com/openharmony-sig/compliance_composition_
                 analysis.
                  2   背景与动机

                  2.1   公共函数干扰
                    本文所指的公共函数是指          TPL  间复用引入的克隆函数, 以及实现常见算法 (如排序算法) 等的相似函数. 这些
                 函数模糊了    TPL  的边界, 影响现有    SCA  技术的有效性    [13] . 图  1  展示了公共函数导致假阳性的一个典型场景: 目标
                 代码  third_party_selinux  复用了  selinux  库, 而后者又包含  libsepol 库的代码. 由于特征库记录了多个复用    libsepol
                 的  TPL, 这些  TPL  共享部分相同的函数, 导致在成分分析过程中, 所有复用              libsepol 的  TPL  都与目标代码匹配, 错
                 误地被识别为目标代码的一部分, 从而产生假阳性.


                                             目标代码                      特征库

                                                         特征匹配成功: 假阳性
                                                         特征匹配成功: 假阳性

                                                         特征匹配成功: 正确

                                                图 1 公共函数造成假阳性示例

                    为此, 已有研究引入了函数诞生时间            [13,14] , 公共函数被归属于函数诞生时间更早的库, 然而, 在融合多个托管
                 仓库构建的特征库中, 函数诞生时间的准确性受到挑战.
                    (1) 版本管理方式的多样性使函数诞生时间难以获取. 尽管                 Git 版本控制系统可提供精确的提交时间戳, 便于
                 追踪函数的创建时间, 但调查结果显示, 约            38.6%  的  C/C++ TPL  未采用  Git 管理 (见表  1), 而是使用其他版本控制
                 平台. 例如, libaiff [20] 库托管于  SourceForge [21] , 其版本控制信息的获取远不如  Git 便捷; C/C++ TPL termcap [22] 通过
                 FTP 服务器 (ftp://ftp.gnu.org/gnu/termcap) 发布不同版本的源代码, 缺乏标准的时间戳信息支持, 进一步加剧了函
                 数诞生时间的提取难度.
                    (2) 版本管理不完善导致获取不准确的函数诞生时间. 已有研究将软件版本的发布时间视为函数的诞生时间.
                 然而, 从多个托管仓库收集的         33 100  个采用  Git 版本管理的  C/C++ TPL  中 (见表  2), 20.0%  的  TPL  未标记任何
                 Release 或  Tag, 导致函数诞生时间难以准确确定. 对此, 已有研究者采用主分支 (master) 的最新提交时间作为近似
                 代替, 但这一方法存在明显的局限性           [15] . 如图  2  所示, SwiftShader 库  [23] 从未发布  Release 和  Tag. 当特征库同时包
                 含了最新版本的      SwiftShader2  和其他  TPL A (复用早期版本的  SwiftShader1) 时, 函数诞生时间的误判会导致函数
                 归属错误: 部分应属于       SwiftShade2  的函数被误认为  TPL A  的一部分, 导致目标代码在与        TPL A  的比较中产生假
                 阳性; 同时, 这些函数被错误剔除, 可能导致目标代码无法匹配                 SwiftShader2, 从而产生假阴性.
   121   122   123   124   125   126   127   128   129   130   131