IEEE 2021
摘要
抽象语言处理器,如编译器和解释器,在构建现代软件中是不可或缺的。语言处理器中的错误可能导致严重后果,如功能不正确,甚至恶意攻击。然而,自动测试语言处理器以发现bug并非易事。现有的测试方法(或模糊程序)要么无法生成高质量(即语义正确的)测试用例,要么只支持有限的编程语言。
在本文中,我们提出了POLYGLOT,这是一个通用的模糊框架,可以生成高质量的测试用例,用于探索不同编程语言的处理器。为了实现通用性,Polyglot通过**统一的中间表示(IR)**消除了编程语言在语法和语义上的差异。为了提高语言的有效性,Polyglot执行约束变异和语义验证,以保持语法正确性和修复语义错误。我们已经应用了9种编程语言的21种流行语言处理器POLYGLOT,并识别了173个新的bug,其中113个bug已修复,分配了18个CVE。我们的实验表明,Polyglot可以支持广泛的编程语言,并且优于现有的模糊器,代码覆盖率提高了30倍。
问题
考虑到特定语言模糊器的复杂性(例如,CSmith[74]由80k行代码组成)和大量编程语言(目前超过700种[3]),为每种语言实现特定的模糊器是不切实际的。这使当前的模糊程序陷入了两难境地:追求高语义有效性牺牲了它们的通用适用性,而保留通用适用性并不能保证测试用例的质量。
目前的模糊程序在测试语言处理器方面存在局限性。基于一般用途变异的模糊器[30,38,76,77]不知道输入结构,并随机翻转输入的位或字节,因此它们很难生成语法正确的输入。最近的研究采用AST或IR中更高级别的变异来保证句法正确性[44,63]。或者,基于生成的模糊器[1,51]利用模型或语法有效地生成结构输入。这些模糊器在通过基于随机位翻转变异的模糊器进行语法检查中展现了优势。他们忽略了生成的测试用例的语义正确性,也没有在语言处理器的优化或执行代码中发现深层的错误。总结:测试用例的语义正确性,语法正确性
研究人员试图将他们的模糊词专门化以获得更高的语义正确性[42,53,74,78]。CSmith[74]执行大量分析,以生成有效的C程序,而不产生未定义的行为。JavaCracpFuffer-[42.53]考虑表达式的类型以避免生成的测试用例中的语义错误。Squirrel[78]解决了SQL的数据依赖性,以生成有效的查询来测试DBMS。不幸的是,这些方法对于一种编程语言来说是高度专业化的。用户需要付出巨大的开发努力才能在新的编程语言上采用它们,考虑到大量的实际语言,这既耗时又不切实际[3]。最近的基于语言的模糊程序[22,44]试图为不同的语言生成正确的测试用例。LangFuzz[44]随机替换变异代码中的每个变量,而Nautilus[22]使用一小组预定义的变量名,并依靠反馈指导来提高语义正确性。然而,这些策略仅在测试允许更多隐式类型转换的语言(如JavaScript和PHP)时有效。
四种常见的语义错误类型 未定义的变量或函数,超出范围的变量或函数,未定义的类型,不匹配的类型
目标
IR生成、约束变异和语义验证
本文的目标是建立一个通用的模糊框架,生成语义正确的输入来测试不同的语言处理器。我们分两步实现目标。首先,我们通过将编程语言的语法和语义嵌入到统一的IR中来消除它们之间的差异,这样我们就可以执行统一的变异或分析,而不考虑底层语言。其次,我们约束我们的变异以生成可能包含语