
WABT 上游提案测试目录 test/spec-new 解析以 wide-arithmetic 测试集为例【免费下载链接】wabtThe WebAssembly Binary Toolkit项目地址: https://gitcode.com/GitHub_Trending/wa/wabt导读test/spec-new/是 WABTWebAssembly Binary Toolkit仓库中一个专门承接「尚未纳入官方 testsuite 的上游提案测试」的目录。本篇文章以其中的 wide-arithmetic.wast 为核心案例剖析该目录的存在意义、测试文件的结构与断言手法包括 overlong 二进制编码与类型检查并结合 opcode.def、lexer-keywords.txt 与 interp.cc 等源码讲清 WABT 对i64.add128、i64.sub128、i64.mul_wide_s、i64.mul_wide_u四个 128 位宽算术操作码的词法、二进制解析与解释器支持现状。读完本文你将掌握 WABT 提案测试的接入机制、测试文件写作范式以及如何定位源码中的对应实现。test/spec-new 目录上游提案测试的过渡缓冲区test/spec-new/README.md 用寥寥数行说明了该目录的全部设计意图本目录包含来自上游提案的测试这些测试要么尚未进入 testsuite 仓库要么位于我们WABT尚未支持/导入的 testsuite 版本中。这句话概括了目录的两种典型用途提案仍在演进中对应的 WebAssembly 提案proposal测试已经写好但官方 [testsuite] 仓库尚未合并testsuite 版本滞后测试已进入 testsuite但当前 WABT 依赖的 testsuite 子模块版本还未包含它无法直接通过常规路径导入。README 明确给出了本目录唯一一个测试文件的出处wide-arithmetic.wast来自 WebAssembly/testsuite 仓库的proposals/wide-arithmetic目录。并注明了一个重要的生命周期约定一旦 WABT 导入了包含该测试的最新版 testsuite 仓库本目录中的该文件即可删除。也就是说test/spec-new是介于「上游提案诞生」与「正式并入官方测试集」之间的过渡缓冲区避免 WABT 在等待 testsuite 更新的空窗期内丢失对这些提案的回归覆盖。这种「先落地、后转正」的测试接入策略保证了 WABT 的工具链wat2wasm、wasm2wat、wast2json等始终与正在演进中的 WebAssembly 提案保持同步验证而不是被动等待官方测试集的一次性大更新。wide-arithmetic.wast128 位宽算术提案测试全解wide-arithmetic.wast 共 470 行是一个结构相当完整的提案测试文件覆盖了功能正确性、二进制编码兼容性与类型检查三个维度。模块定义四个导出函数测试文件开头定义一个 WAT 模块导出了 4 个包装函数分别对应 wide-arithmetic 提案的 4 个操作码(module (func (export i64.add128) (param i64 i64 i64 i64) (result i64 i64) local.get 0 local.get 1 local.get 2 local.get 3 i64.add128) (func (export i64.sub128) (param i64 i64 i64 i64) (result i64 i64) local.get 0 local.get 1 local.get 2 local.get 3 i64.sub128) (func (export i64.mul_wide_s) (param i64 i64) (result i64 i64) local.get 0 local.get 1 i64.mul_wide_s) (func (export i64.mul_wide_u) (param i64 i64) (result i64 i64) local.get 0 local.get 1 i64.mul_wide_u) )从中可以提炼出这 4 个操作码的类型签名操作码参数结果语义i64.add1284 × i64低 64 位、高 64 位各两个操作数2 × i64和 的低 64 位、高 64 位128 位加法i64.sub1284 × i642 × i64128 位减法i64.mul_wide_s2 × i642 × i64带符号 128 位宽乘法i64.mul_wide_u2 × i642 × i64无符号 128 位宽乘法这些签名与 opcode.def 中的操作码定义一一对应WABT_OPCODE(I64, I64, I64, I64, I64, 0, 0xfc, 0x13, I64Add128, i64.add128, ) WABT_OPCODE(I64, I64, I64, I64, I64, 0, 0xfc, 0x14, I64Sub128, i64.sub128, ) WABT_OPCODE(I64, I64, I64, I64, ___, 0, 0xfc, 0x15, I64MulWideS, i64.mul_wide_s, ) WABT_OPCODE(I64, I64, I64, I64, ___, 0, 0xfc, 0x16, I64MulWideU, i64.mul_wide_u, )可以看到四个操作码都属于0xfc前缀段子码依次为0x13–0x16类型位中___表示「无」与mul_wide_*只有 2 个参数的事实吻合。功能断言简单用例 随机生成用例测试的主体部分是assert_return断言分为两类简单用例覆盖了最容易出错的边界情况例如 128 位加法的进位传播(assert_return (invoke i64.add128 (i64.const 1) (i64.const 0) (i64.const -1) (i64.const 0)) (i64.const 0) (i64.const 1))这里低 64 位1 (-1) 0产生向高 64 位的进位高 64 位0 0 进位 1结果应为(0, 1)。类似地减法用例覆盖借位传播(assert_return (invoke i64.sub128 (i64.const 0) (i64.const 0) (i64.const 1) (i64.const 1)) (i64.const -1) (i64.const -2))mul_wide的简单用例则验证符号处理i64.mul_wide_s (-1) × (-1) → (1, 0)而无符号版本中i64.mul_wide_u (-1) × 1 → (-1, 0)即0xFFFFFFFFFFFFFFFF × 1的低 64 位仍为全 1。随机生成用例数量庞大且分布全面文件随后给出了各 20 个随机生成的i64.add128、i64.sub128、i64.mul_wide_s、i64.mul_wide_u用例共 80 个覆盖大量跨符号、跨进位边界的随机 64 位操作数组合例如(assert_return (invoke i64.add128 (i64.const 1) (i64.const -5381447440966559717) (i64.const 1020031372481336745) (i64.const 1)) (i64.const 1020031372481336746) (i64.const -5381447440966559716))这类随机用例由提案作者离线生成、固化到测试文件中用于对实现做统计意义上的正确性检验比手工边界用例更能暴露进位/借位链路中的隐蔽缺陷。overlong 二进制编码测试对 LEB128 的宽松性验证测试中段插入了一个完整的module binary模块其用意非常明确验证二进制读取器接受每个操作码的 overlong过长LEB128 编码。WABT 中这些操作码的二进制编码由前缀0xfc LEB128 编码的子码构成例如i64.add128的标准编码为fc 13而测试给出的是\fc\93\80\00 ;; i64.add128 (overlong) \fc\94\00 ;; i64.sub128 (overlong) \fc\95\80\80\80\00 ;; i64.mul_wide_s (overlong) \fc\96\80\80\00 ;; i64.mul_wide_u (overlong)LEB128 是允许「加长表示」的变长整数编码0x93 0x80 0x00的低 7 位依次为0x13、0x00、0x00解码结果仍是0x13只是本可 1 字节完成的值被写成了 3 字节。这类 overlong 编码通常被规范视为可接受canonical 之外的形式读取器应当宽容处理。这段测试因此专门验证 WABT 的 binary-reader.cc 在解析0xfc前缀段时能正确容忍并解码这些非规范编码——文件中的assert_return断言确认了这些模块不仅可被解析其函数调用结果也完全符合预期。assert_invalid类型检查的负向测试测试文件的最后一部分针对 4 个操作码各给出两组assert_invalid用例验证验证器validator能够拒绝签名不匹配的模块。例如(assert_invalid (module (func (param i64 i64 i64 i64) (result i64) local.get 0 local.get 1 local.get 2 local.get 3 i64.add128) ) type mismatch)以及参数个数不足3 个参数而非 4 个的用例。这确认了 WABT 的共享验证器对宽算术操作码实施了严格的栈类型与结果数量检查错误消息统一为type mismatch。源码视角WABT 对这 4 个操作码的支持现状词法层关键字注册src/lexer-keywords.txt 中为四个操作码注册了词法关键字及其运算元类别i64.add128, TokenType::Quaternary, Opcode::I64Add128 i64.mul_wide_s, TokenType::Binary, Opcode::I64MulWideS i64.mul_wide_u, TokenType::Binary, Opcode::I64MulWideUQuaternary四元对应 4 参数操作码Binary二元对应 2 参数操作码与提案签名完全对应。该文件经生成流程产出 src/prebuilt/lexer-keywords.cc供wat2wasm、wast2json等工具在文本解析阶段识别这些助记符——这也是wide-arithmetic.wast能被正确解析的前提。解释器层尚未实现在 src/interp/interp.cc 中这 4 个操作码被显式标记为未实现case O::I64Add128: case O::I64Sub128: case O::I64MulWideS: case O::I64MulWideU: return TRAP(not implemented);从源码结构可以推断WABT 的解释器wasm-interp、spectest-interp目前对这四个宽算术操作码一律返回not implemented陷阱尚未给出真正的执行语义。这也从侧面解释了为什么这些测试仍停留在test/spec-new的「过渡区」——工具链的解析、验证链路已就绪但运行时语义支持还在推进中。如何运行这些测试WABT 的测试由 test/run-tests.py 驱动每个.wast测试文件通常伴随一个描述测试方式的.txt元数据文件。本目录的 wide-arithmetic.txt 内容如下;;; TOOL: wast2json ;;; STDIN_FILE: test/spec-new/wide-arithmetic.wast它声明了两个关键信息TOOL: wast2json本次测试使用wast2json工具src/tools/wast2json.cc处理测试文件负责将.wast中的模块、断言逐一转换验证文本解析、二进制编码与验证器的正确性STDIN_FILE测试文件通过标准输入喂给工具这是 WABT 测试框架对「零长度文件」「stdin 输入」等场景的通用支持方式。运行全部测试只需执行python3 test/run-tests.py单独验证本目录时可将其作为run-tests.py的过滤参数传入。测试通过的标准是wast2json能无错误地完成解析与类型检查且所有assert_return、assert_invalid断言得到预期结果。小结test/spec-new/是 WABT 与上游 WebAssembly 提案演进保持同步的窗口它承接尚未进入官方 testsuite 的提案测试并在 testsuite 更新后随时可被清空转正。以wide-arithmetic.wast为例可以看到一份合格的提案测试需要同时覆盖功能正确性简单边界 大规模随机用例、二进制编码兼容性overlong LEB128 的宽容解析与类型安全assert_invalid负向用例。而在 WABT 源码侧这四个 128 位宽算术操作码已具备完整的词法关键字、0xfc前缀段二进制定义与验证支持唯独解释器运行时不支持——这正是它们仍停留在test/spec-new、尚未并入主线测试目录的直接原因。关注 test/spec-new 目录的增删变化即可追踪 WABT 对 wide-arithmetic 等新提案的跟进进度。【免费下载链接】wabtThe WebAssembly Binary Toolkit项目地址: https://gitcode.com/GitHub_Trending/wa/wabt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考