一种基于错误注入的软件缺陷检测方法、装置及存储介质
文献发布时间:2024-04-18 20:01:30
技术领域
本发明属于软件缺陷检测领域,更具体地,涉及一种基于错误注入的软件缺陷检测方法、装置及存储介质。
背景技术
软件在运行过程中,可能会遇到各种错误,一个健壮的程序需要能够正确处理这些错误。这些错误一般分为两类,一类是输入相关的错误,另一类是偶发的错误。常见的软件测试技术,例如模糊测试技术理论上可以检出第一类错误的错误处理部分中的缺陷,但对于第二类偶发的错误,由于错误发生的可能性较低,在测试过程中触发的概率较低,所以很难发现这类错误的错误处理部分中的缺陷。因此,研究人员提出了软件故障注入的(Software Fault Injection,SFI)技术,在可能发生错误的位置处注入错误,来控制错误稳定发生,从而测试相应的错误处理部分,增强软件的健壮性。
然而,常规的SFI技术需要人工标注注入错误的位置,这不仅需要对软件充分了解,还需要付出大量的劳动时间,不适合大规模的对不同的软件进行测试。并且,针对一个错误函数可能有多个对应的调用点,并不是每个调用点都存在缺陷,对每个调用点都进行缺陷检测,影响软件测试的效率。另外,在动态测试过程中,由于错误函数对应的调用点存在多次调用,现有技术中,在每一次的测试中都需要计算函数调用栈的哈希,而在控制错误是否发生时,并不需要知道具体的哈希值,这导致测试过程比较耗时。
发明内容
针对现有技术的缺陷和改进需求,本发明提供了一种基于错误注入的软件缺陷检测方法、装置及存储介质,其目的在于提升测试效率。
为实现上述目的,按照本发明的第一方面,提供了一种基于错误注入的软件缺陷检测方法,包括:
S1、获取待测程序中的错误函数列表;
S2、遍历所述错误函数列表中每个错误函数的错误处理部分,计算有错误处理部分的调用点处的指令序列的哈希值序列;其中,所述错误函数的错误处理部分由对应的指令序列构成;
S3、针对同一个错误函数,计算每一个调用点处的指令序列的哈希值序列与其它调用点处的指令序列的哈希值序列的相似度,并对得到的相似度求均值后作为对应调用点处的相似度;若对应调用点处的相似度低于预设的第一阈值,则所述调用点为待测的可疑调用点;所述错误函数列表中每个错误函数对应的待测可疑调用点构成待测的调用点列表;
S4、在所述待测的调用点列表的调用点处插桩,并采用错误注入方法对待测程序进行动态测试,得到缺陷点的位置。
进一步地,S4中,在所述待测的调用点列表的调用点处插桩时,还包括:对每个调用点添加控制块,所述控制块用于控制在注入点处是否注入错误,其中,插桩后的调用点为所述注入点;所述控制块控制在注入点处是否注入错误,包括:
设置回调函数,所述回调函数用于在每次动态测试中,查询一个注入点是否应该注入错误;
若所述注入点需要注入错误,则待测程序将所述注入点对应的错误函数的返回值设置为-1或者空指针,使所述注入点发生错误;
若所述注入点不需要注入错误,则待测程序直接调用所述注入点对应的错误函数。
进一步地,所述回调函数,包括:
静态计数器,设置在每个调用点处,用于统计每次动态测试中,每个注入点对应的错误函数被调用的次数,以产生错误函数被触发的时序序列,记所述时序序列对应的注入点编号依次为1-N;
第一共享内存区域,用于存储每次测试中需要所述控制块注入错误的注入点,若当前调用点处的静态计数器的值与所述错误函数被触发的时序序列中的某个注入点编号相等,表明需要在该注入点处注入错误,否则,不需要在该注入点注入错误;
第二共享内存区域,用于存储测试路径中所有的错误函数被触发的时序序列。
进一步地,S4中,采用错误注入方法对待测程序进行动态测试,得到缺陷点的位置,包括:
S41、采用模糊测试工具生成当前的测试用例,并将测试用例输入至待测程序中,运行待测程序;
S42、获取当前路径中的注入点,所述当前路径中的注入点为从所述第二共享内存区域中获取的当前的错误函数被触发的时序序列对应的注入点;将所述时序序列对应的注入点编号依次填入所述第一共享内存区域中,若填入的注入点编号与当前调用点处的静态计数器的值相等,则所述控制块在所述注入点处注入错误;
S43、若在测试路径上收集到新的注入点,将所述新的注入点存储至所述第二共享内存区域,并更新当前的错误函数被触发的时序序列;
S44、重复S42-S43,直至达到预设的第一测试时间或者用户终止;
S45、重复S41-S44,直至达到预设的第二测试时间或者用户终止,获得测试过程中缺陷点的位置。
进一步地,当达到预设的测试时间或者预设测试轮次后,S41中,采用模糊测试工具生成当前的测试用例时,模糊测试的种子的选择概率P
其中,N
进一步地,S45中,获得测试过程中缺陷点的位置,包括:
每当注入点注入错误后,再次运行待测程序,得到输出的崩溃日志;
解析所述崩溃日志中注入点位置的程序调用栈,以及崩溃产生位置的程序调用栈;
使用编辑距离算法比较所述注入点位置的程序调用栈和所述崩溃产生位置的程序调用栈的相似度,若所述相似度不超过预设的第三阈值,则认为所述注入点位置为真实的缺陷位置。
进一步地,S2中,计算有错误处理部分的调用点处的指令序列的哈希值序列,包括:
针对所述指令序列中的函数调用型指令,用指令的类型和被调用的函数名计算对应的哈希值;
针对所述指令序列中的控制流指令,用指令的类型、控制流跳转的来源位置和跳转的目的位置,计算对应的哈希值;
针对所述指令序列中的其它类型指令,用指令的类型计算对应的哈希值。
进一步地,S1中,获取待测程序中的错误函数列表,包括:
S11、获取待测程序中的候选错误函数列表Func
S12、遍历待测程序,并统计出所述候选错误函数列表中的每个候选错误函数在对应调用点处被调用的次数C
S13、计算每个所述候选错误函数被调用的比值P
进一步地,S11中,包括:
编译待测程序,并遍历编译后的待测程序,统计编译后的待测程序中具有如下特征的函数:
函数的返回值为指针型或整型;
函数的返回值为分支控制语句的参数,且所述分支控制语句后紧邻至少两个后继分支;
将满足上述特征的函数作为候选错误函数,得到所述候选错误函数列表。
按照本发明的另一方面,提供了一种基于错误注入的软件缺陷检测装置,包括计算机可读存储介质和处理器;
所述计算机可读存储介质用于存储可执行指令;
所述处理器用于读取所述计算机可读存储介质中存储的可执行指令执行第一方面任一项所述的方法;
或/和,提供了一种计算机可读存储介质,其上存储有计算机程序,所述程序被处理器执行时实现如第一方面任一项所述的方法。
总体而言,通过本发明所构思的以上技术方案,能够取得以下有益效果:
(1)本发明的基于错误注入的软件缺陷检测方法,考虑到针对一个错误函数可能有多个对应的调用点,并不是每个调用点都存在缺陷,通过遍历错误函数列表中每个错误函数的错误处理部分,计算有错误处理部分的调用点处的指令序列的哈希值序列,计算调用点处的相似度,相似度低于预设阈值,则认为该调用点处的错误处理部分与该错误函数其它调用点处的错误处理部分不同,用相似度作为衡量标准之一,确定待测的可疑调用点,缩小了待测空间,提升了后续测试的效率。
(2)进一步地,在动态测试过程中,本发明设计的控制块,采用时序控制一个位置在不同的测试中是否需要注入错误,用时序代替具体的哈希值,无需在每一次的测试中都计算哈希值,减少了注入点的代码量与计算量,进一步提高了测试的效率。
(3)进一步地,在动态测试过程中,采用模糊测试工具的输出样例进行测试,在运行路径上通过控制块依次对当前满足要求的注入点注入错误,并在注入错误后改变了运行逻辑的新路径上收集新的注入点,本发明的这种自动化的通用错误处理代码方式,能够快速准确的测试出路径上的缺陷点,避免了人工标注注入错误的位置,适合大规模的对不同的软件进行测试。
(4)进一步地,本发明在达到预设的测试时间之后,不再选择代码覆盖率高的种子,而是考虑到每个种子的被选择概率受其运行路径上注入点的数量影响,将模糊测试的种子的选择概率设置为P
(5)进一步地,本发明中,观察到软件测试中的主要缺陷是由函数调用指令和控制流相关指令这两种特殊的指令缺失或者使用错误导致的,因此,在进行哈希编码时,将函数调用指令和控制流相关指令进行对应的特殊处理,设计上较为简单,且能够提升确定待测的可疑调用点的效率和精度,进而提升软件测试的效率和精度。
(6)进一步地,通过统计在待测程序中会返回错误的函数形式具有的特征,并将具备该相应特征的函数作为候选错误函数,可以提升测试精度。
附图说明
图1为本发明的基于错误注入的软件缺陷检测方法示意图。
图2为本发明实施例中采用错误注入方法对待测程序进行测试过程中收集到新的注入点的示意图。
图3为本发明实施例中使用模糊测试器注入错误并完成测试的流程图。
具体实施方式
为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅用以解释本发明,并不用于限定本发明。此外,下面所描述的本发明各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。
在本发明中,本发明及附图中的术语“第一”、“第二”等是用于区别类似的对象,而不必用于描述特定的顺序或先后次序。
如图1所示,本发明的基于错误注入的软件缺陷检测方法,主要包括:
S1、获取待测程序中的错误函数列表;
S2、遍历该错误函数列表中每个错误函数的错误处理部分,计算有错误处理部分的调用点处的指令序列的哈希值序列H
S3、针对同一个错误函数,计算每一个调用点处的指令序列的哈希值序列与其它调用点处的指令序列的哈希值序列的相似度,并对得到的相似度求均值后作为该调用点处的相似度;依次计算出每一个调用点处的相似度,若计算出的调用点处的相似度低于预设的第一阈值,则认为该调用点处的错误处理部分与该错误函数其它调用点处的错误处理部分不同,记为待测的可疑调用点,即待测的可疑调用点处的错误处理部分可能有缺陷;其中,此处的调用点是指有错误处理部分的调用点;
按照同样的方法,计算错误函数列表中每个错误函数对应的可疑调用点,得到待测的调用点列表;
S4、重新编译待测程序,并在待测的调用点列表的调用点处插桩,采用错误注入方法对待测程序进行动态测试,得到缺陷点的位置。在本发明实施例中,采用的错误注入方法为SFI方法。
具体地,S1中,获取待测程序中的错误函数列表,包括:
S11、获取待测程序中的候选错误函数列表,记为:Func
S12、遍历待测程序,并统计出候选错误函数列表中的每个候选错误函数在对应调用点处被调用的次数C
S12中,针对每一个候选错误函数,其在对应调用点处被调用的次数与未被调用的次数之和等于该候选错误函数对应的调用点总数。针对候选错误函数列表中的候选错误函数FunC
S13、针对每个候选错误函数,计算其被调用的比值P
具体地,本发明实施例的S11中,获取待测程序中的候选错误函数列表,包括:
编译待测程序,并遍历编译后的待测程序,统计编译后的待测程序中具有如下特征的函数作为候选错误函数:
(a)函数的返回值为指针型或整型;
(b)函数的返回值为分支控制语句的参数,且该分支控制语句后紧邻至少两个后继分支;
将满足上述特征的函数作为候选错误函数,得到候选错误函数列表。
本发明实施例中,采用使用LLVM框架编译待测程序,获取程序的中间表示字节码(LLVM IR Bitcode),记为IR
在待测程序中,会返回错误的函数形式一般满足上述特征,通过统计具有上述特征的函数作为候选错误函数,可以提升测试精度。
对应地,作为优选,本发明实施例的S12中,统计每个候选错误函数在对应调用点处被分支控制语句调用的次数和未被调用的次数。
具体地,S2中,计算有错误处理部分的调用点处的指令序列的哈希值序列H
针对指令序列中的函数调用型指令,用该指令的类型和其被调用函数的函数名计算对应的哈希值;
针对指令序列中的控制流相关指令,用该指令的类型、控制流跳转的来源位置和跳转的目的位置,计算对应的哈希值;
针对指令序列中的其它类型指令,直接采用其指令的类型计算对应的哈希值;在本发明实施例中,忽略LLVM内置函数的指令。
本发明中,观察到软件测试中的主要缺陷是由函数调用指令和控制流相关指令这两种特殊的指令缺失或者使用错误导致的,因此,在进行哈希编码时,将函数调用指令和控制流相关指令进行对应的特殊处理,设计上较为简单,且能够提升确定待测的可疑调用点的效率和精度,进而提升软件测试的效率和精度。
具体地,本发明实施例S3中,采用编辑距离算法计算两个不同调用点处的指令序列的哈希值序列相似度,计算公式为:
Sim
其中,i,j代表同一个错误函数在两处不同调用位置的指令序列的哈希值序列,ED函数用来计算哈希值序列i,j之间的编辑距离,Max函数用于取哈希值序列i,j长度中较长的序列长度。
对应地,得到的调用点处的相似度为:
其中,
针对同一个错误函数,计算出的每一个调用点处的相似度越低,说明该调用点处的错误处理部分与该错误函数其它调用点处的错误处理部分有明显不同;特别的,如果错误函数在该调用点处没有错误处理部分,对应的相似度为0,将对应的调用点同样作为待测的可疑调用点,参与后续测试。
S4中,被处插桩后的调用点称为注入点,在待测的调用点列表的调用点处插桩时,还包括对每个调用点添加控制块,该控制块用于在对待测程序进行动态测试过程中,控制对应错误函数是否返回错误,也即,如何在控制在注入点处是否注入错误,同时,在测试路径上收集新的注入点。具体地,控制块在注入点处是否注入错误的过程包括:
设置回调函数,该回调函数用于在每次动态测试中,查询该注入点是否应该注入错误;其中,该回调函数为程序链接阶段链接的相应的运行时组件;
若该注入点需要注入错误,则待测程序不调用该注入点对应的错误函数,而是直接将该错误函数的返回值设置为-1或者空指针,使该注入点发生错误;
若该注入点不需要注入错误,则待测程序直接调用该注入点对应的错误函数。
具体地,回调函数包括:静态计数器、第一共享内存区域及第二共享内存区域;
静态计数器设置在每个调用点处,用于统计每次动态测试中,每个注入点对应的错误函数被调用的次数,产生错误函数被触发的时序序列,记该时序序列对应的注入点编号依次为1-N;其中,错误函数每调用一次,计数器加1;
第一共享内存区域,用于存储每次测试中,模糊测试器需要控制块注入错误的注入点,若当前调用点处的静态计数器的值与错误函数被触发的时序序列中的某个注入点编号相等,则回调函数返回真值,表明需要在该位置注入错误,则返回负值,表明不需要在该时刻注入错误;
第二共享内存区域,用于存储动态测试中测试路径中所有的错误函数被触发的时序序列,也即所有的可以注入错误的注入点编号。
S4中,如图2-图3所示,采用错误注入方法对待测程序进行测试,得到缺陷点的位置,包括:
S41、采用模糊测试工具生成当前的测试用例,并将测试用例输入至待测程序中,运行待测程序;本发明实施例中,采用的模糊测试工具为AFL;
S42、获取当前路径中的注入点(也即图2中的反馈注入点),其中,当前路径中的注入点为从第二共享内存区域中获取的当前的错误函数被触发的时序序列对应的注入点,将该时序序列对应的注入点编号依次填入第一共享内存区域中,当填入的注入点编号与当前调用点处的静态计数器的值相等,则控制块在该注入点处注入错误,否则,不需要在该注入点处注入错误;
S43、若在测试路径上收集到新的注入点,将其存储在第二共享内存区域,更新当前的错误函数被触发的时序序列;其中,图2中的全局注入点为一轮测试(对应于相同的测试用例)收集到的所有注入点,用于判断是否收集到新的注入点,也即,新的注入点为全局注入点与反馈注入点的差集;
S44、重复S42-S43,直至达到预设的第一测试时间或者用户终止;
S45、重复S41-S44,直至达到预设的第二测试时间或者用户终止,获得测试过程中缺陷点的位置。
作为优选,在采用模糊测试工具生成测试用例时,在模糊测试的种子选择阶段使用启发式算法,在预设的测试时间或者测试轮次(每一轮测试对应于生成一次测试用例,S42-S43的循环过程作为一轮测试,对应于相同的测试用例)后,为了提升测试精度,模糊测试的种子的选择概率P
其中,N
在本发明实施例中,在测试的半小时之前,种子的选择使用模糊测试器的原方法;在测试半小时后,种子的选择概率采用P
本发明在达到预设的测试轮次或者时间之后,不再选择代码覆盖率高的种子,而是考虑到每个种子的被选择概率受其运行路径上注入点的数量影响,将模糊测试的种子的选择概率设置为P
具体地,S45中,获得测试过程中缺陷点的位置,包括:
每当注入点注入错误后,再次运行待测程序,得到输出的崩溃日志;其中,在测试过程中,可以使用第三方检测工具,例如AddressSanitizer,MemorySanitizer等生成测试过程中的崩溃日志;
对测试过程中产生的崩溃日志进行过滤及输出,得到缺陷点的位置,具体包括:
解析崩溃日志中注入点位置的程序调用栈,以及崩溃产生位置的程序调用栈;
使用编辑距离算法比较两个调用栈的相似度,若相似度不超过预设的第三阈值,则认为该注入点位置为真实的缺陷位置。也即,相似度越高,该注入点位置与崩溃位置重合度越高,假阳率越高。在本发明实施例中,预设的第三阈值为0.9,当相似度高于0.9时,忽略该崩溃,也即,该注入点并非为真正的缺陷位置。
本发明的基于错误注入的软件缺陷检测方法,考虑到针对一个错误函数可能有多个对应的调用点,并不是每个调用点都存在缺陷,通过遍历错误函数列表中每个错误函数的错误处理部分,计算有错误处理部分的调用点处的指令序列的哈希值序列,计算调用点处的相似度,相似度低于预设阈值,则认为该调用点处的错误处理部分与该错误函数其它调用点处的错误处理部分不同,用相似度作为衡量标准之一,确定待测的可疑调用点,缩小了待测空间,提升了后续测试的效率。
在动态测试过程中,本发明设计的控制块,采用时序控制一个位置在不同的测试中是否需要注入错误,用时序代替具体的哈希值,无需在每一次的测试中都计算哈希值,减少了注入点的代码量与计算量,进一步提高了测试的效率。
在动态测试过程中,采用模糊测试工具的输出样例进行测试,在运行路径上通过控制块依次对当前满足要求的注入点注入错误,并在注入错误后改变了运行逻辑的新路径上收集新的注入点,本发明的这种自动化的通用错误处理代码方式,能够快速准确的测试出路径上的缺陷点,避免了人工标注注入错误的位置,适合大规模的对不同的软件进行测试。
本发明的基于错误注入的软件缺陷检测方法,通过S1-S3计算待测的调用点列表的过程属于静态分析过程,通过S4确定缺陷点的位置的过程属于动态分析过程,静态分析过程以一种模式匹配的方法确认候选的错误函数,并使用基于统计的方法对这些函数进行筛选,最终获得能够插桩位置的待测的调用点列表,该方法减少了人工工作量,并提供较为准确的结果。在动态分析过程中,编译时对预选位置进行插桩,同时链接上控制错误注入的运行时组件(控制块),接着使用模糊测试工具的输出样例进行测试,在运行路径上所有的错误注入点处依次注入错误,并根据错误点的数量引导模糊测试工具的种子选择过程,迭代产生更多的测试用例,最终对测试中产生的错误日志(崩溃日志)进行过滤并输出,得到缺陷点的位置。本发明的这种静态分析与动态分析相结合的方式,可以快速准确的检测出程序错误处理代码中的缺陷。
本发明还提供了一种基于错误注入的软件缺陷检测装置,包括计算机可读存储介质和处理器;
计算机可读存储介质用于存储可执行指令;
处理器用于读取计算机可读存储介质中存储的可执行指令执行上述实施例中的基于错误注入的软件缺陷检测方法;
本发明还提供了一种计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现上述实施例中的基于错误注入的软件缺陷检测方法。
本领域的技术人员容易理解,以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。
- 全差分运放的一种共模启动电路
- 应用于全差分运放电路的连续时间共模反馈电路