任何语言的简单程序减速器

2021-03-29 03:36:00

我一直在模糊编译器,以获得更熟悉的语言,如稳固和迪姆(智能合同),以及像ZIG这样的上升语言。更多关于这种模糊的努力。有趣的部分是看着崩溃编译器的程序。重新调度程序以在错误报告中提交......更少。事情是,我想提交对维护者的少量和可理解的程序,并在大约5次报告后用手做事令人繁琐。有用于在那里减少程序的工具,但没有真正检查了我想要的框。所以我写了Comby-Reducer来检查这些盒子,事情变得更有趣:

基本上是以基本上的语言语法或结构化格式(包括例如,DSL)语法感知(不仅仅是正则表达式),但没有严格要求语法定义易于定义和包括/排除转换(声明性,没有脚本)容易查看它所做的内容(所以我可以调整转换)易于安装和调用大输入快速?大多数崩溃的投入都很小,这并不重要

Comby-Reducer使用Comby构建,它支持重写Aprogram的解析树的句法结构的轻量级方式,如表达式和功能块。 Comby Islanguage-Invustn并理解代码,字符串和评论语法的基本语法。特定于语言特定的解析器,Comby使用GenericParser适用于DSL的语法构造和较少的主题流程。您可以在此处了解更多关于Comby的信息。

Comby-Reducer使用从Comby' s核心acserengine中转换的JavaScript库,以及将程序转换为固定点的几个功能。

让我们继续例子。如果您愿意,您可以了解程序如何通过验证本帖子末尾的资源来了解编程。

模块M {Resource Struct {} struct< t> {}有趣t0(x8:u8,x64:u64,x128:u128){继续; (FALSE作为U8); (真实为U128); (()作为U64); (1,1); (0作为BOOL); (0作为地址); r =(0和r); (0作为杯< u8>); (0 AS()); (0 AS(U64,U8)); (X" 1234"作为U64); }}

Comby-Reducer将程序减少到我乐意在错误报告中提交的内容:

移动语法是一种类似的生锈语法,与许多语言一样,使用括号()和括号{}来描绘与暂停解析树对应的嵌套表达式。 Comby-Reducer了解这些句法构造品,并且可以在平衡括号和大括号内转换内容(但如果像(发生在字符串或注释中),则不会困惑。

Const BitField = Packed Struct {A:U3,B:U3,C:U2,}; fn(error.hi)u3 {return bar(& bit_field.b); fn(x:* const u3)u3 {return x。*; }导出fn()使用{return @sizeof(@typeof(foo)); }

合同c {函数(uint256 [calldata x,uint256 s,uint256 e)(uint256){(x [s:e])。长度; }}

Pragma实验Abiencoderv2;合同C {函数(UINT256 [] CallData X,UINT256 S,UINT256 E)(UINT256){(x [s:e])。长度; }函数(UINT256 [] CallData X,UINT256 S,UINT256 E,UINT256 SS,UINT256 EE)(UINT256){return uint256 [](x [s:e] [ss:ee])。长度; }函数(uint256 [calldata x,uint256 s)(uint256){return uint256 [](x [s:])。长度; }函数(uint256 [] calldata x,uint256 e)(uint256){return uint256 [](x [:e])。长度; }函数(uint256 [] calldata x,uint256 s,uint256 e,uint256 idx)(uint256){11111111111111111111256 [](x [s:e])[idx]; }函数(UINT256 [] CallData X,UINT256 S,UINT256 E,UINT256 IDX)(UINT256){return x [s:e] [idx]; }函数(uint256 [] calldata x,uint256 s,uint256 idx)(uint256){return x [s:] [idx]; }函数(uint256 [] calldata x,uint256 e,uint256 idx)(uint256){return x [:e] [idx]; }}

Comby-Reducer使用大约20个转换来产生上述。这些是在repo中,但您也可以通过扩展下面的标签来获得物种感觉来查看它们的样本。使用Comby语法进行的转换,我们将走过其中一些。

[delete_paren_content] ='(:[1])' ='()' ='嵌套' [delete_brace_content] =' {:[1]}' =' {}' ='嵌套' #有助于将空白机构放在同一行中的换行符以进行线路删除。 [blank_brace] =' {}' =' {}' [delete_line] =':[x \ n]' ='' [delete_string_content] ='":[x]"' ='""' [remove_first_paren_element] ='(:[1],:[2])' ='(:[2])'

此转换与平衡括号(包括NewLines)之间的任何内容匹配并删除内容。 :[1]是绑定根本内容的变量。默认情况下,Comby-Reducer将尝试在文件的顶级申请Intransformation,无论它所看到(...)。规则='嵌套'告诉Comby-Reducer,它还应该尝试在其他匹配的其他匹配(...)内的(...)中的匹配匹配。一般来说,括号是一个常见的语法来嵌套在程序中的表达式,因此添加规则=&#39是有意义的;嵌套'

程序语法经常使用呼叫或函数类似的语法,即派生的逗号分隔参数或括号内的参数。此转换尝试在此类语法中移除。此转换没有规则部分,因为它可能会尝试嵌套indure的摘要:[1]或:[2]。但是,我们很容易添加它。

默认转换不是非常语言和工作良好的,并巩固了我处理的语言(巩固,移动,Zig)到Smallhuman可辨别的程序。当然,您可以使用所需的句法特异性定义您的OwnTransformations。例如,我们在JavaScript中获得循环的Mightremove:

在某些转换序列之后,块可能最终为空,但包含空格。要咬紧这些,我添加了转换

此转换只需删除连续的空格(包括换行符)。在转弯时,这通常会导致Func(){}的内容减少,这已最终通过删除行的转换删除。好的!

因为我有一种简单的方法来引入新的转变,所以我想要更多地进入变换的表现方式。这请帮助我了解沿外的帮助减少,甚至只是发现改善格式化的变换。

在这里,我只想在一个线上将第一对括号配对组在fn foo(error.hi)u3 {}。所以我添加了与往返括号内的所有内容匹配的内容:

为了使这个过程有点剧本,我添加了一种重播转换的方法。 Comby-Reducer采用-record参数,并且可以使用comby-reduce-replay重播输出。这使得可以逐步通过该过程。在其中我手动逐步通过Zig减少的示例。

您的浏览器不支持视频标记。看看下面的屏幕截图。

------ 000.Step 2021-03-26 04:50:53.499923-04:00 +++++ 001.Step 2021-03-26 04:50:54.572018-04:00 @ | -1,16 +1,16 ========================================== ================== | | Const Bitfield = Packed Surrut {|答:U3,| B:U3,| C:U2,| }; | | fn foo(error.hi)u3 {!|返回栏(& bit_field.b); | } | | FN Bar(X:* Const U3)U3 {|返回x。*; | } | |导出fn条目()使用{return @sizeof(@typeof(foo)); }

------ 001.STEP 2021-03-26 04:50:54.572018-04:00 +++++ 002.STEP 2021-03-26 04:50:55.616110-04:00 @ | -1,16 +1,16 ========================================== ================== | | Const Bitfield = Packed Surrut {|答:U3,| B:U3,| C:U2,| }; | | fn foo(错误.hi)u3 {|返回栏(); | } | !| FN Bar(X:* Const U3)U3 {|返回x。*; | } | |导出fn条目()使用{return @sizeof(@typeof(foo)); }

------ 002.Step 2021-03-26 04:50:55.616110-04:00 +++++ 003.Step 2021-03-26 04:50:57.132244-04:00 @ | -1,16 +1,12 ========================================== ================== | !| Const BitField = Packed STRUCT {!| A:U3,!| B:U3,!| C:U2,!| }; | | fn foo(错误.hi)u3 {|返回栏(); | } | | fn bar()u3 {|返回x。*; | } | |导出fn条目()使用{return @sizeof(@typeof(foo)); }

------ 003.Step 2021-03-26 04:50:57.132244-04:00 +++++ 004.Step 2021-03-26 04:50:57.748298-04:00 @ | -1,12 +1,10 ========================================== ================== | | Const BitField = Packed STRUCT {}; | !| fn foo(error.hi)u3 {!|返回栏(); !| } | | fn bar()u3 {|返回x。*; | } | |导出fn条目()使用{return @sizeof(@typeof(foo)); }

------ 004.STEP 2021-03-26 04:50:57.748298-04:00 +++++ 005.STEP 2021-03-26 04:50:58.356352-04:00 @ | -1,10 +1,8 ========================================== ================== | | Const BitField = Packed STRUCT {}; | | fn foo(error.hi)u3 {} | !| fn bar()u3 {!|返回x。*; !| } | |导出fn条目()使用{return @sizeof(@typeof(foo)); }

------ 005.STEP 2021-03-26 04:50:58.356352-04:00 +++++ 006.STEP 2021-03-26 04:50:59.464450-04:00 @ | -1,8 +1,6 ========================================== ================== | | Const BitField = Packed STRUCT {}; | | fn foo(error.hi)u3 {} | - | fn bar()u3 {} - | |导出fn条目()使用{return @sizeof(@typeof(foo)); }

------ 007.Step 2021-03-26 04:51:01.000586-04:00 +++++ 008.Step 2021-03-26 04:51:01.596638-04:00 @ | -1,5 +1,4 ========================================== ================== - | Const BitField = packed struct {}; | | fn foo(error.hi)u3 {} | |导出fn条目()使用{return @sizeof(@typeof(foo)); }

比较AFL-TMIN减少是有用的,这是我们AFL型稳定性和移动性的可容易获得的减速机。由于AFL-TMIN利用覆盖范围信息,因此可以在最小化输入的大小时可以非常好,而无论格式如何(它都适用于我们的崩溃程序,以及JPEG等二进制格式)。在Chesame的时候,这个捕获的所有覆盖引导方法牺牲了一些能力的输入域的特性。对于错误报告,它可以将某些语法(如括号)或以其他方式保留语义,格式化或符号名称有用。 Comby-Reducer可以轻松覆盖输入的过程。例如,Comby-Reducer的减少的移动程序给出了

AFL-TMIN品种具有一些冗余语法,热切地删除了无需可读性的WhiteSpaceth,并重命名原始功能T0至T.塞尼特不一定是坏的,但没有多少调整空间。

模块M {struct< t1,t2,t3> {}有趣的cpy< c:copyable>(){} fun t3< u,c:copyable>(){cpy(box3< u,u}} {cy> {}); }}

模块M {struct {}资源结构{} struct< t> {}结构< t1,t2,t3> {}有趣的两个< r:资源,c:copyable>(r:r,c:c){abort 0}有趣的cpy< c:copyable>(c:c){abort 0}有趣rsrc< r:资源>( r:r){abort 0} fun t0(){均(s {},硬币{});两个(0,硬币{})}有趣的t1< r:资源,c:copyable>(){两个(box< c> {},box< r lt; {})} fun t2< r:资源,c:copyable&gt ;(){rsrc(box3< c,c,c,c> {}); cpy(box3< r,c,c,c> {}); cpy(box3< c,r,c> {}); cpy(box3< c,c,r> {}); cpy(box3< c,r,r> {}); cpy(box3< r,c,r> {}); cpy(box3< r,r,c> {}); cpy(box3< r,r,r> {}); }有趣的t3< u,c:copyable>(){cpy(box3< u,c,c,c,c> {}); cpy(box3< c,u,c> {}); cpy(box3< c,c,u> {}); cpy(box3< c,u,u> {}); cpy(c,box3< u,u> {}); cpy(box3< u,u,c> {}); cpy(box3< u,u,u> {}); }}

请参阅GitHub存储库的例子和更多技术细节。请注意,Comby-Reducer是新的,简单地发展,尚未进行测试;随意发布GitHub问题跟踪器。如果您想帮助WorthStransformations Comby语法,请在Gitter通道中发布。

那里有很多减速工具和技术。我最喜欢探索和比较这些更深入的学术,但塞中的工程师没有时间。 🙂

因此,这里有一些相关的工具和主题,您可能需要进一步探索。 在Fuzzing书中减少章节提供了更深入的减速剂解释,特别是基于语法的减少。 在这里,Comby-Reducer可以被视为基于语法的唯一的语法,无需您编写或理解语法,也不需要编写任何脚本或访问解析树。 相反,转换被声明地指定,并吸引了许多语言共同的直观的NotionsAround语法。 此处提到的最喜欢的工具是C-Drefeic(这也适用于非C语言)。 它是一个特别好的资源,解释有趣的Testwhich可以进一步指导输入改变的方式和何时何种。