C++关于C++静态扫描工具QAC的介绍和使用(看这一篇就够了)
今天在搜集了一些有关静态分析工具以及编码规范的相关资料后,个人对这些资源进行整合,汇总后得到这篇文章。这篇文章的内容主要包含QAC以及一些安全编码规范(例如MISRA)的背景介绍,为什么要使用QAC进行静态代码分析,以及怎么使用QAC的相关诊断信息进行代码修正和生成分析报告。
其中,基于现有的QAC部署方式,由于许可证数量的限制和一些其他原因,开发者平台对QAC做了封装和集成,我们仅需使用其对外提供的接口做代码检查,并通过Dashboard Web端查看分析结果,省去了配置编码规范和导入项目文件等一系列繁琐的行为,因此,关于如何正确使用Helix QAC进行代码静态检查此文不再涉及。
我的理解:这个工具演化的过程,就好比未来的某一天,我们的开发工作暂时告一段落,大家抽个时间开个会,坐在一起进行前一阵的工作复盘,会上负责人说:”对于前一阵开发和测试过程中遇到的一些问题,如何写出高质量的代码从而避免以后的开发过程中出现的类似问题,将bug扼杀在摇篮中,大家有什么好的建议?“。于是,大家你一言我一语,商量了一些方案:比如禁止使用goto语句啊,必须使用{}将代码块进行分隔啊…等等,于是,在会议的末尾,根据大家讨论的结果,我们将这些内容书面化,写成了我们自己的规范,并在以后的开发中不断的改善与完善这个规范,久而久之,也便成了一份正式的安全编码规范,为了使这份规范更正式,我们可以在后期进行ISO标准认证或是一些其他认证,引导其走向国际。
后来,其他公司由于业务关系,也开始涉足我们现在的开发领域,那么此时摆在他们面前的有两条路,一是像当初的我们一样白手起家,自己把这条路走一遍,但这就避免不了要踩很多坑,发展到后期,他们也能形成一套自己的规范,但是却花费了大量的资源,时间。二是直接购买并恪守我们的规范,帮助他们规避开发过程中有可能遇到的一些问题。有的公司选择了走第一条路,有的公司选择了走第二条路,这也就形成了今天的这种局面。
关于为什么要进行静态代码分析,可能在你读完这篇文章之后你能找到很多答案,但是真正的目的我认为只有两个字:合规。
一、背景介绍 1.1 QAC与PRQA公司QA-C 是由英国 PRQA 公司(该公司于2023年被美国Perforce公司收购)开发的静态代码分析工具,该公司是静态代码分析领域的行业先驱。
Perforce(PRQA)公司是AUTOSAR组织在代码静态分析领域的唯一会员,负责功能安全软件架构的相关标准制定工作,参与编写了C++14编码指南,制定了AUTOSAR测试方案,并应用其开发的静态测试工具Helix QAC在AUTOSAR Adaptive Platform演示代码上执行代码静态测试。
Helix QAC作为代码静态分析领域的先驱,不仅仅提供针对AUTOSAR C++的诊断,还支持MISRA C/C++、HICPP、JSF AV C++、CERT、CWE编码规范包,其精准的诊断消息和强大的软件生命周期管理平台为全球3000多个整车厂和零部件供应商所信赖。
早在上世纪80年代,由于C语言在嵌入式领域存在诸多无法被替代的优点,也就很早被应用于工业领域。随着软件在安全相关的系统中的广泛使用,这些软件自身代码的安全性便成了使用者和开发者共同关注的焦点。如何给这些关键代码的安全性提供基础保障?慢慢的开始有一些学者和组织投身于代码安全编程规范的研究和制定中去。
MISRA C/C++ 安全编程规范的制订开始较早,也是目前该领域成果的典范。
PRQA公司是是MISAR C&C++编码委员会的创始会员,也是MISRA C&C++委员会最具影响力的会员,后来也成为了AUTOSAR规范指定工作组成员。
MISRA全称为Motor Industry Software Reliability Association,即汽车工业软件可靠性联合会。该组织最早起源于英国政府发起的“SafeIT”项目。该组织从成立至今,一直致力于为车载电子系统中的嵌入式软件制订开发指导方针。
MISRA组织在1994年11月出版了《面向车载软件的开发指南(Development guidelines for vehicle based software)》。该文件是汽车行业在功能安全领域的第一份指导性文件,代表了当时汽车行业嵌入式开发人员对安全开发的共识。
在英国政府资助项目结束后,MISRA以独立非盈利实体的形式继续运作,出版了MISRA C、MISRA C++和MISRA安全论证指南等具有里程碑意义的标准及规范。
1.2 编程规范的发展作为一款静态代码分析工具,它的使用自然离不开判断代码是否安全的一系列编程规范包,编码规范包包括汽车领域常用的MISRA C/C++,AUTOSAR,信息安全领域常用的CERT C/C++,CWE C/C++ 等等,同时还支持企业自定义自己的编码规范包,比如21年新发布的跟现代集团定制的编码规范包。下面简要介绍MISRA C/C++编码规范的发展历程。
MISRA C 起源于《面向车载软件的开发指南》中确定的“标准化编程语言的限制性子集”这一要求。考虑到 C 语言当时已被大量应用在汽车行业的嵌入式开发中,MISRA组织便组织编写了MISRA C 安全编程规范,旨在帮助汽车界开发“C”中的安全相关系统,从那时起,MISRA C已被更广泛的嵌入式系统社区所采用,并已成为在关键系统中使用“C”的主要国际编码指南。MISRA C指南被广泛接受为满足1994年基于车辆的软件的MISRA开发指南和IEC 61508对语言子集的要求。
由于后来受到其它领域从业人员的关注与使用,在其随后的修订中涉及了来自除汽车以外相关嵌入式开发行业的场景和需求。时至今日,MISRA C 已经成为高安全性嵌入式开发领域中 C 语言开发的事实标准。
事情继续发展,现在C++处于“C”曾经占据的位置;尽管许多人认为,它不应该用于关键系统,但它在该领域的使用正在增长,而且这种增长没有一套共同的指导方针。MISRA最近完成了一套在关键系统中使用C++的指南的编制工作,该指南的输出将是一套类似于为“C”编制的指南。该文件被称为《在关键系统中使用C++语言的MISRA C++指南》,于2008年6月5日发布并正式发布。
1.3 MISRA C 编程规范内容介绍在最新的MISRA C:2012中,其前半部分整体介绍编程规范的的相关内容,包括编程规范的定位、MISRA C的背景、开发及检测工具选择和MISRA C的使用方法;后半部分描述编程规范的具体内容,包括规范内容介绍、分类和每条规范的详细解释。
根据规范的重要性,规范条目可分为强制规范(Mandatory guidelines),要求规范(Required guidelines)和建议规范(Advisory guidelines)。
指令与规则
根据规范的可检测性,可以分为指令(Directives)和规则(Rules)两类。
指令是一种描述性的指导规范,它无法提供执行符合性检查所需的完整描述。为了能够进行检查,需要给评测人员提供额外的信息,如设计文件或需求说明。
指令部分主要分为:实现、编译与构建、要求追踪、代码设计四个部分,共16条规范。
规则可以对相关要求提供完整的描述,评测人员或静态分析工具可以在不需要额外信息的情况下检查源代码是否符合对应规则。
规则部分是整个编程规范的核心,共分为22个部分,共142条规则。
所有规则根据重要性分类统计如下表:
1.4 主流的一些安全编码规范介绍 1.4.1 三种主流的安全编码规范 CERT CCERT 编码规范由软件工程研究所SEI 的CERT部门发布,它包含了编码和执行错误,还有低级的设计错误,旨在清除代码中可能导致网络安全的编码惯例以及未定义的行为。
CERT C每条规范包含:
标题描述不合规代码举例合规代码解决方案举例例外情形CERT C这样定义漏洞:允许攻击者违反显式或隐式安全政策的一系列情况。缺陷可能很小,甚至可能都不影响软件的性能或者运行结果。然而它会在遭遇攻击的时候暴露问题,导致严重的安全后果。
CWECWE(Common Weakness Enumeration)是从架构、设计、乃至编码层面描述代码中常见的网络安全问题。由美国MITRE公司发起。CWE可以作为识别、减少、预防漏洞的基线。
CWE按优先级排列漏洞列表。优先级最高的25个条目来自二十多个不同组织的统计数据,他们基于使用频率和重要性评估了每个C代码缺陷,很多CWE列表中的缺陷都和缓冲溢出相关。我们的设计人员、编程者、测试者可以通过遵循CWE来消除典型错误,在编码阶段清除漏洞。
(ps: CERT及最新发布的CWE都包含针对C++的信息安全规范,在此不做详述)
MISRA CMISRA编码规范由汽车工业软件可靠性协会发布,可以用来防止会导致安全问题和安全漏洞的错误编码,为安全相关系统的开发提供了最好的实践指导,可以说MISRA 是嵌入式系统最为理想的编码规范。目前应用最为广泛的MISRA C:2012 Amendment 1发布于2016年,它新增了C编码的安全指导,包括新的规则和指令,也包含了合规代码和不合规代码的举例说明。
1.4.2 相同与差异三种编码方案都可以应用于C代码信息安全测试,那么它们之间又有什么关联?
MISRA C 2012 Rule 18.1“A pointer resulting from arithmetic on a pointer operand shall address an element of the same array as that pointer operand”
这条规则与CERT ARR30-C做的是同样的事情
CERT ARR30-C“Do not form or use out-of-bounds pointers or array subscripts.”
这条规则都与CWE C的多个典型安全漏洞相关,比如:
CWE-119“Improper Restriction of Operations within the Bounds of a Memory Buffer.”
也就是软件对内存缓冲区执行操作,但是它可以从缓冲区的预期边界之外的内存位置进行读写操作。
需要注意的是CERT C 是基于C11设计的,MISRA C 2012是基于C99设计的,MISRA C 2012-Addendum 3专门阐述了两者之间规则的异同点。具体如下图:
以上数据汇总了CERT C和MISRA C 2012的规则覆盖情况,并根据规则覆盖强度分为:
· Strong:由CERT C规则处理的代码行为多个MISRA C2012规则覆盖
· Weak:由CERT C规则处理的代码行为仅被一个MISRA C2012指令/Rule1.3覆盖
· None:独立于MISRA C 2012的CERT C规则
虽然MISRA C 2012对CERT C的覆盖达到了60%以上,但两者依据的C标准不同,且存在19%的差异。
结合工程实际,我们需要选择性遵循相关编码规范:
如果开发代码为C,并且要求综合全面的信息安全规则覆盖度,那么您需要同时执行MISRA C 2012(incl. Amendment 1)和CERT C如果开发代码为C++且基于AUTOSAR架构,建议您全面执行AUTOSAR Coding Guidelines如果您使用C++开发且要求遵循MISRA C++ 2008,那么建议您同时执行CERT C++,以保证所开发车辆的信息安全以上静态测试方案的高效执行,还需借助强有力的静态代码分析器,才能避免CWE中的典型安全漏洞。作为代码静态测试领域的领跑者,Perforce(PRQA)公司的Helix QAC无疑是各大厂商的第一选择。它可以自动执行MISRA、CERT、CWE、AUTOSAR Coding Guidelines等编码规范,拥有超过1600条诊断消息,每一条诊断消息都对应着一种违反规定的语言使用,并且提供详细的指标度量,以及可视化报表,量化代码质量,帮助测试人员深入了解数据流和控制流,大大提高静态测试效率,确保代码的信息安全。
1.5 目前在用的编码规范 1.5.1 AUTOSAR Coding Guidelines2017年,AUTOSAR组织基于C++14标准发布了新的编码准则——AUTOSAR Coding Guidelines,这一准则是MISRA C++2008的延伸,它为应用现代C++语言编写安全和任务关键型嵌入式系统提供了有效指导。也是咱们目前在用的编程规范。
其实AUTOSAR编码标准与MISRA C++2008存在高度的共性,在处理新语言特性的使用上存在少量差异,所以如果我们采用了合适的自动代码静态分析方案,完成MISRA C++2008到AUTOSAR Coding Guidelines的迁移并不是一件难事。
1.5.2 AUTOSAR Coding Guidelines和现有编码规范的区别和联系这应该是广大开发人员比较关心的一部分,用两个成语来概括AUTOSAR Coding Guidelines:兼容并蓄、独树一帜。因为它涉及了一系列已有的编程标准,又根据Adaptive Platform制定了独有的规则。2018年3月,AUTOSAR Coding Guidelines发布了402条规则,其中138条直接取自MISRA C++2008。
此外AUTOSAR还引用了如下编码标准:
Joint Strike Fighter Air Vehicle C++ coding standards (JSF AV C++)High Integrity C++ coding standard Version 4.0 (HICPP)CERT C++ coding standard (CERT)C++ Core guidelines (C++ CORE)Google C++ Style Guide在AUTOSAR编码标准中,有“对已有编码标准的可追溯性”的章节,它详述了MISRA,HICPP,JSF,C++ Core guidelines,和CERT编码规则与AUTOSAR编码标准的关联度,并分成如下几类:“完全相同”、“微小差别”、“显著差别”、“不采用”,详见下表:
1.5.3 开发团队应该采用AUTOSAR编码规范吗?很多人可能存在这样的疑问:能不能用MISRAC++2008测试C++14的代码?是否有必要采用AUTOSAR Coding Guidelines?
严格来讲,使用C++14编译器编译的代码是不能遵从MISRA规范的。如果用MISRAC++2008测试C++14的代码,就肯定会出现违反项,我们需要对每一项违反进行说明,并用其他方法再一次检查违反项代码。换句话说,是有可能证明C++14代码符合MISRA规范的,但过程很艰苦。AUTOSAR Coding Guidelines帮助开发人员摆脱了这种复杂情况。
所以,开发团队采用AUTOSAR编码规范是毋庸置疑的。不仅如此,如果您的项目需要按照C++14编码并且需要说明该项目符合ISO26262功能安全标准,那么AUTOSAR编码规范就是无可替代的,因为在AUTOSAR编码规范之前没有其他的编码标准是为了支持符合C++14编写的安全关键型软件而设计的。
下表是各编码规范支持的C++语言版本:
二、QAC是什么?结合以上背景资料,现在对Helix QAC下一个定义。
Helix QAC是代码静态测试工具,依据C和C++编码规则自动扫描代码对规则的违背。开发团队在开发过程的早期就可以用它来检测缺陷,因为此时修改代码是最方便也最经济的。Helix QAC因此自动化强制实施代码编程标准,比如MISRA,保证代码的合规性。
三、为什么需要进行静态代码分析 3.1 汽车领域软件开发所面临的风险首先,我们先看一下在汽车领域软件开发所面临的风险:
现在的车载软件的代码量已经达到了1亿到3亿行,汽车——作为一种与人身安全息息相关的交通工具,其内部的安全等级一般也设置的比较高,所以一般的整车厂会让他们的代码过一些功能安全认证,使代码合规,符合行业标准,比如ISO26262,ISO21434,但是我们项目交付普遍遇到的一些的预算常常是有限的,再加上项目交付的压力,就导致代码合规面临一些风险。
3.2 Helix QAC静态分析的优势接下来,我们来看一下使用Helix QAC进行静态代码分析的优势:
业界领先的编码规范覆盖度,持续支持新版本的C++标准;丰富的命令行,更容易实现自动化,方便与持续集成系统进行融合;不断改进的数据流分析,可以找出代码运行时错误,如缓存溢出,数组访问越界,未定义行为等。你可以看到他对各个编码规范的覆盖度都基本上达到了百分百,最少的也是半分之八十三左右。
2023年1月的版本支持C++17标准,AUTOSAR规范覆盖度达到91%;2023年2月份的版本对于AUTOSAR规范的覆盖度达到了93%;2023年3月份的版本支持了C++20标准,AUTOSAR规范覆盖度达到了94%;它有以下功能特性:
遵循代码标准 遵循编码和工业标准。Helix QAC自动审查代码,确保它们符合用户选择的编码标准。合规性报告可视化地提醒用户哪些代码需要多加留意。Helix QAC支持多种C和C++编码标准,提供相应的合规性模块,也支持标准的客户化定制。
检查