Compiler Fuzzing through Deep Learning
模糊测试是发现编译器中错误的有效技术手段,但成功的模糊测试需要对编译器支持的每种语言进行大量的开发工作,并且通常会遗漏部分对于语言空间的测试。本文介绍DeepSmith,一种通过推断编译器输入的生成模型来加速编译器的验证方法。本方法基于大量的开源代码构建真实项目中代码结构的学习模型,并使用该模型自动生成数以万计的程序。最后,本文通过差分测试方法来揭示编译器中的错误。
在进行模糊测试时,随机生成的有效或部分有效的数据被作为输入投给编译器。任何类型的异常行为,包括崩溃、冻结和错误的二进制文件,都意味着编译器的Bug。编译器中的崩溃和冻结很容易检测,但是二进制文件是否正确编译却很难判断。为解决这个问题,本文通过差分测试,通过将生成的代码和一组输入形成一个测试用例,在多个测试平台上编译和执行。如果测试用例应该具有确定性行为,但是在测试床上的输出不同时,进而发现Bug。
目前先进的CSmith方法通过定义和采样C编程语言的语法来生成大型的随机程序。复杂的静态和动态分析可确保程序不受未定义行为的影响。虽然CSmith已成功应用于识别编译器中的数百个错误,但它和类似的方法有一个明显的缺点,即它们代表了一项庞大的任务,需要彻底了解目标编程语言。
DeepSmith利用深度学习技术来自动构建人类如何编写代码的概率模型,而不是刻意地将语法定义到同一端。通过在手写代码语料库上训练深度神经网络,它能够推断出编程语言的语法和语义以及常见的结构和模式。本方法极大地简化并加速了该过程。生成的程序的表现力仅受语料库中包含的内容的限制,而不受开发人员的专业知识或可用时间的限制。
DeepSmith包含三个核心组件:1)随机程序的生成模型;2)测试工具;3)用于差分测试的投票启发式算法。
1)生成模型。为编译器生成测试用例比较困难,因为它们的输入是高度结构化的。使用正确的结构生成文本需要专业的知识,并且对于每一种新的语言都要从头开始。在DeepSmith中,我们将该测试用例生成问题视为无监督的机器学习任务,采用深度学习技术来构建编写程序的模型。
2)测试工具。本文开发了一种首先预定预期的函数原型的参数并为它们随机生成数据。起初,本工作使用了CLSmith测试工具。该工具是基于内核没有输入和ulong缓冲区作为写入结果的单个参数的假设。然而只有0.2%的GitHub内核共享此结构。本工作开发了一个首先从函数原型确定预期的参数,再为这些参数生成数值的工具。与生成模型不同,该测试工具是基于特定语言和领域知识的。
3)用于差分测试的投票启发式算法。在先前的工作中,对编译器的程序输出进行投票已被用于规避oracle问题并检测错误编译。本文扩展了此方法,不仅能够描述错误编译,还能够描述异常构建和崩溃。
1)本文提出了一种新颖、自动和快速的用于编译器模糊测试的程序,通过真实的代码而不是专家定义的语法来推断编程语言的语法和结构。本方法代码量比现有方法少两个数量级、并且仅需要不到一天的时间来训练模型;
2)在发现Bug的能力上,本方法发现的Bug数量总数与现有方法相似,但是能够找到现有工具未能发现的Bug,并且能够覆盖更多的编译器组件;
3)在对真实代码进行建模时,本方法产生的测试用例比其他方法更易于解释,没有任何昂贵的还原过程。
本文由南京大学软件学院2019级博士生章许帆翻译转述
留言与评论(共有 0 条评论) |