健全性¶
WebAssembly 的类型系统是健全的,这意味着它在 WebAssembly 语义方面既具有类型安全又具有内存安全。例如
健全性也有助于确保其他属性,最显著的是函数和模块作用域的封装:没有局部变量可以在其自身函数之外访问,并且没有模块组件可以在其自身模块之外访问,除非它们被明确导出或导入。
定义 WebAssembly 验证的类型规则只涵盖 WebAssembly 程序的静态组件。为了准确地陈述和证明健全性,类型规则必须扩展到抽象运行时的动态组件,即存储、配置和管理指令。[1]
结果¶
结果 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\)¶
对于值 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}_i\) 在 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 中
设 \(t^\ast\) 为所有 \(t_i\) 的连接。
那么该结果在结果类型 \([t^\ast]\) 下是有效的。
结果 \(\href{../exec/runtime.html#syntax-trap}{\mathsf{trap}}\)¶
存储有效性¶
以下类型规则指定了何时运行时存储 \(S\) 是有效的。有效存储必须包含函数、表、内存、全局变量和模块实例,这些实例本身相对于 \(S\) 是有效的。
为此,每种实例都由相应的函数、表、内存或全局变量类型进行分类。模块实例由模块上下文进行分类,模块上下文是作为模块类型重新利用的常规上下文,用于描述模块定义的索引空间。
存储 \(S\)¶
在 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}\) 中,每个函数实例 \(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}_i\) 必须在某种函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}_i\) 下是有效的。
在 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{tables}}\) 中,每个表实例 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}_i\) 必须在某种表类型 \(\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}_i\) 下是有效的。
在 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{mems}}\) 中,每个内存实例 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}_i\) 必须在某种内存类型 \(\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}_i\) 下是有效的。
在 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{globals}}\) 中,每个全局变量实例 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}_i\) 必须在某种全局变量类型 \(\href{../syntax/types.html#syntax-globaltype}{\mathit{globaltype}}_i\) 下是有效的。
在 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{elems}}\) 中,每个元素实例 \(\href{../exec/runtime.html#syntax-eleminst}{\mathit{eleminst}}_i\) 必须在某种引用类型 \(\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}}_i\) 下是有效的。
在 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{datas}}\) 中,每个数据实例 \(\href{../exec/runtime.html#syntax-datainst}{\mathit{datainst}}_i\) 必须是有效的。
那么该存储是有效的。
函数实例 \(\{\href{../exec/runtime.html#syntax-funcinst}{\mathsf{type}}~\href{../syntax/types.html#syntax-functype}{\mathit{functype}}, \href{../exec/runtime.html#syntax-funcinst}{\mathsf{module}}~\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}, \href{../exec/runtime.html#syntax-funcinst}{\mathsf{code}}~\href{../syntax/modules.html#syntax-func}{\mathit{func}}\}\)¶
该函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\) 必须是有效的。
模块实例 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\) 必须在某个上下文 \(C\) 中是 有效的。
在上下文 \(C\) 下,函数 \(\href{../syntax/modules.html#syntax-func}{\mathit{func}}\) 必须在函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\) 下是 有效的。
那么函数实例在函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\) 下是有效的。
宿主函数实例 \(\{\href{../exec/runtime.html#syntax-funcinst}{\mathsf{type}}~\href{../syntax/types.html#syntax-functype}{\mathit{functype}}, \href{../exec/runtime.html#syntax-funcinst}{\mathsf{hostcode}}~\mathit{hf}\}\)¶
该函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\) 必须是有效的。
令 \([t_1^\ast] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^\ast]\) 为函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\)。
对于每个 有效的 存储 \(S_1\) 扩展 \(S\) 以及每个其类型与 \(t_1^\ast\) 相符的值序列 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\)
那么函数实例在函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\) 下是有效的。
注意
此规则指出,如果存储和参数满足适当的先决条件,则执行宿主函数必须满足存储和结果的适当后置条件。后置条件与 执行规则 中调用宿主函数的条件相匹配。
调用函数的任何存储都被认为是当前存储的扩展。这样,函数本身就能对未来的存储做出充分的假设。
表格实例 \(\{ \href{../exec/runtime.html#syntax-tableinst}{\mathsf{type}}~(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}~t), \href{../exec/runtime.html#syntax-tableinst}{\mathsf{elem}}~\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast \}\)¶
表格类型 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}~t\) 必须是 有效的。
\(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast\) 的长度必须等于 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}.\href{../syntax/types.html#syntax-limits}{\mathsf{min}}\)。
对于表格元素 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^n\) 中的每个引用 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}_i\)
引用 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}_i\) 必须在引用类型 \(t\) 下是 有效的。
那么表格实例在表格类型 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}~t\) 下是有效的。
内存实例 \(\{ \href{../exec/runtime.html#syntax-meminst}{\mathsf{type}}~\href{../syntax/types.html#syntax-limits}{\mathit{limits}}, \href{../exec/runtime.html#syntax-meminst}{\mathsf{data}}~b^\ast \}\)¶
内存类型 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}\) 必须是 有效的。
\(b^\ast\) 的长度必须等于 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}.\href{../syntax/types.html#syntax-limits}{\mathsf{min}}\) 乘以 页面大小 \(64\,\mathrm{Ki}\)。
那么内存实例在内存类型 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}\) 下是有效的。
全局实例 \(\{ \href{../exec/runtime.html#syntax-globalinst}{\mathsf{type}}~(\href{../syntax/types.html#syntax-mut}{\mathit{mut}}~t), \href{../exec/runtime.html#syntax-globalinst}{\mathsf{value}}~\href{../exec/runtime.html#syntax-val}{\mathit{val}} \}\)¶
全局类型 \(\href{../syntax/types.html#syntax-mut}{\mathit{mut}}~t\) 必须是 有效的。
值 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}\) 必须在值类型 \(t\) 下是 有效的。
那么全局实例在全局类型 \(\href{../syntax/types.html#syntax-mut}{\mathit{mut}}~t\) 下是有效的。
元素实例 \(\{ \href{../exec/runtime.html#syntax-eleminst}{\mathsf{type}}~t, \href{../exec/runtime.html#syntax-eleminst}{\mathsf{elem}}~\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast \}\)¶
对于元素 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^n\) 中的每个引用 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}_i\)
引用 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}_i\) 必须在引用类型 \(t\) 下是 有效的。
那么元素实例在引用类型 \(t\) 下是有效的。
数据实例 \(\{ \href{../exec/runtime.html#syntax-datainst}{\mathsf{data}}~b^\ast \}\)¶
数据实例是有效的。
导出实例 \(\{ \href{../exec/runtime.html#syntax-exportinst}{\mathsf{name}}~\href{../syntax/values.html#syntax-name}{\mathit{name}}, \href{../exec/runtime.html#syntax-exportinst}{\mathsf{value}}~\href{../exec/runtime.html#syntax-externval}{\mathit{externval}} \}\)¶
该 外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}\) 必须与某个 有效 的 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathit{externtype}}\) 匹配。
然后导出实例是有效的。
模块实例 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\)¶
在 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{types}}\) 中的每个 函数类型 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}_i\) 必须是 有效 的。
对于 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{funcaddrs}}\) 中的每个 函数地址 \(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}_i\),外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{func}}~\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}_i\) 必须与某个 有效 的 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathsf{func}}~\href{../syntax/types.html#syntax-functype}{\mathit{functype}}'_i\) 匹配。
对于 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{tableaddrs}}\) 中的每个 表格地址 \(\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}_i\),外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{table}}~\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}_i\) 必须与某个 有效 的 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathsf{table}}~\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}_i\) 匹配。
对于 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{memaddrs}}\) 中的每个 内存地址 \(\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}_i\),外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{mem}}~\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}_i\) 必须与某个 有效 的 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathsf{mem}}~\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}_i\) 匹配。
对于 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{globaladdrs}}\) 中的每个 全局地址 \(\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}_i\),外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{global}}~\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}_i\) 必须与某个 有效 的 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathsf{global}}~\href{../syntax/types.html#syntax-globaltype}{\mathit{globaltype}}_i\) 匹配。
对于 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{elemaddrs}}\) 中的每个 元素地址 \(\href{../exec/runtime.html#syntax-elemaddr}{\mathit{elemaddr}}_i\),元素实例 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{elems}}[\href{../exec/runtime.html#syntax-elemaddr}{\mathit{elemaddr}}_i]\) 必须是 有效 的,并且与某个 引用类型 \(\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}}_i\) 匹配。
对于 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{dataaddrs}}\) 中的每个 数据地址 \(\href{../exec/runtime.html#syntax-dataaddr}{\mathit{dataaddr}}_i\),数据实例 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{datas}}[\href{../exec/runtime.html#syntax-dataaddr}{\mathit{dataaddr}}_i]\) 必须是 有效 的。
在 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{exports}}\) 中的每个 导出实例 \(\href{../exec/runtime.html#syntax-exportinst}{\mathit{exportinst}}_i\) 必须是 有效 的。
对于 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{exports}}\) 中的每个 导出实例 \(\href{../exec/runtime.html#syntax-exportinst}{\mathit{exportinst}}_i\),名称 \(\href{../exec/runtime.html#syntax-exportinst}{\mathit{exportinst}}_i.\href{../exec/runtime.html#syntax-exportinst}{\mathsf{name}}\) 必须与 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{exports}}\) 中出现的任何其他名称不同。
令 \({\href{../syntax/types.html#syntax-functype}{\mathit{functype}}'}^\ast\) 是所有 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}'_i\) 按顺序的串联。
令 \(\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}^\ast\) 是所有 \(\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}_i\) 按顺序的串联。
令 \(\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}^\ast\) 是所有 \(\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}_i\) 按顺序的串联。
令 \(\href{../syntax/types.html#syntax-globaltype}{\mathit{globaltype}}^\ast\) 是所有 \(\href{../syntax/types.html#syntax-globaltype}{\mathit{globaltype}}_i\) 按顺序的串联。
令 \(\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}}^\ast\) 是所有 \(\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}}_i\) 按顺序的串联。
令 \(m\) 是 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{funcaddrs}}\) 的长度。
令 \(n\) 是 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{dataaddrs}}\) 的长度。
令 \(x^\ast\) 是从 \(0\) 到 \(m-1\) 的 函数索引 序列。
那么该模块实例在 上下文 \(\{\href{../valid/conventions.html#context}{\mathsf{types}}~\href{../syntax/types.html#syntax-functype}{\mathit{functype}}^\ast,\) \(\href{../valid/conventions.html#context}{\mathsf{funcs}}~{\href{../syntax/types.html#syntax-functype}{\mathit{functype}}'}^\ast,\) \(\href{../valid/conventions.html#context}{\mathsf{tables}}~\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}^\ast,\) \(\href{../valid/conventions.html#context}{\mathsf{mems}}~\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}^\ast,\) \(\href{../valid/conventions.html#context}{\mathsf{globals}}~\href{../syntax/types.html#syntax-globaltype}{\mathit{globaltype}}^\ast,\) \(\href{../valid/conventions.html#context}{\mathsf{elems}}~\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}}^\ast,\) \(\href{../valid/conventions.html#context}{\mathsf{datas}}~{\mathrel{\mbox{ok}}}^n,\) \(\href{../valid/conventions.html#context}{\mathsf{refs}}~x^\ast\}\) 中是有效的。
配置有效性¶
为了将 WebAssembly 的 类型系统 与其 执行语义 联系起来,指令的类型规则 必须扩展到 配置 \(S;T\),这将 存储 与执行 线程 联系起来。
配置和线程按其 结果类型 进行分类。除了存储 \(S\) 之外,线程还在返回类型 \(\href{../syntax/types.html#syntax-resulttype}{\mathit{resulttype}}^?\) 下进行类型化,该类型控制是否以及以何种类型允许使用 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{return}}\) 指令。这种类型在管理 \(\href{../exec/runtime.html#syntax-frame}{\mathsf{frame}}\) 指令内部的指令序列中除外 (\(\epsilon\))。
最后,帧 按帧上下文进行分类,帧上下文扩展了帧关联的 模块实例 的 模块上下文,并包含该帧包含的 局部变量。
配置 \(S;T\)¶
然后,配置使用 结果类型 \([t^\ast]\) 是有效的。
线程 \(F;\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast\)¶
令 \(\href{../syntax/types.html#syntax-resulttype}{\mathit{resulttype}}^?\) 为当前允许的返回类型。
令 \(C'\) 与 \(C\) 相同,但 \(\href{../valid/conventions.html#context}{\mathsf{return}}\) 设置为 \(\href{../syntax/types.html#syntax-resulttype}{\mathit{resulttype}}^?\)。
在上下文 \(C'\) 下,指令序列 \(\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast\) 必须是 有效的,并且具有某种类型 \([] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t^\ast]\)。
然后,该线程使用 结果类型 \([t^\ast]\) 是有效的。
帧 \(\{\href{../exec/runtime.html#syntax-frame}{\mathsf{locals}}~\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast, \href{../exec/runtime.html#syntax-frame}{\mathsf{module}}~\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\}\)¶
模块实例 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\) 必须是 有效的,并且具有某种 模块上下文 \(C\)。
每个 值 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}_i\) 在 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 中必须是 有效的,并且具有某种 值类型 \(t_i\)。
令 \(t^\ast\) 为所有 \(t_i\) 按顺序连接的结果。
令 \(C'\) 与 \(C\) 相同,但将 值类型 \(t^\ast\) 添加到 \(\href{../valid/conventions.html#context}{\mathsf{locals}}\) 向量前面。
然后,该帧使用 帧上下文 \(C'\) 是有效的。
管理指令¶
指定 管理指令 的类型规则如下。除了 上下文 \(C\) 之外,这些指令的类型化是在给定的 存储 \(S\) 下定义的。为此,所有先前的类型化判断 \(C \vdash \mathit{prop}\) 都被概括为包括存储,如 \(S; C \vdash \mathit{prop}\),通过将 \(S\) 隐式添加到所有规则中 - \(S\) 从未被现有规则修改,但它在下面给出的 管理指令 的额外规则中被访问。
\(\href{../exec/runtime.html#syntax-trap}{\mathsf{trap}}\)¶
该指令的类型为 \([t_1^\ast] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^\ast]\),对于任何 值类型 序列 \(t_1^\ast\) 和 \(t_2^\ast\) 均有效。
\(\href{../exec/runtime.html#syntax-ref.extern}{\mathsf{ref{.}extern}}~\href{../exec/runtime.html#syntax-externaddr}{\mathit{externaddr}}\)¶
该指令的类型为 \([] \href{../syntax/types.html#syntax-functype}{\rightarrow} [\href{../syntax/types.html#syntax-reftype}{\mathsf{externref}}]\)。
\(\href{../exec/runtime.html#syntax-ref}{\mathsf{ref}}~\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}\)¶
该 外部函数值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{func}}~\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}\) 必须是 有效 的,并具有 外部函数类型 \(\href{../syntax/types.html#syntax-externtype}{\mathsf{func}}~\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\)。
那么该指令的类型为 \([] \href{../syntax/types.html#syntax-functype}{\rightarrow} [\href{../syntax/types.html#syntax-reftype}{\mathsf{funcref}}]\)。
\(\href{../exec/runtime.html#syntax-invoke}{\mathsf{invoke}}~\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}\)¶
该 外部函数值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{func}}~\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}\) 必须是 有效 的,并具有 外部函数类型 \(\href{../syntax/types.html#syntax-externtype}{\mathsf{func}} ([t_1^\ast] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^\ast])\)。
那么该指令的类型为 \([t_1^\ast] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^\ast]\)。
\(\href{../exec/runtime.html#syntax-label}{\mathsf{label}}_n\{\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}_0^\ast\}~\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}}\)¶
指令序列 \(\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}_0^\ast\) 必须是 有效 的,并具有某些类型 \([t_1^n] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^*]\)。
令 \(C'\) 与 \(C\) 相同,但其 上下文 中的 结果类型 \([t_1^n]\) 被添加到 \(\href{../valid/conventions.html#context}{\mathsf{labels}}\) 向量的前端。
在上下文 \(C'\) 下,指令序列 \(\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast\) 必须是 有效 的,并具有类型 \([] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^*]\)。
那么该复合指令的类型为 \([] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^*]\)。
\(\href{../exec/runtime.html#syntax-frame}{\mathsf{frame}}_n\{F\}~\href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}}\)¶
在返回类型 \([t^n]\) 下,该 线程 \(F; \href{../syntax/instructions.html#syntax-instr}{\mathit{instr}}^\ast\) 必须是 有效 的,并具有 结果类型 \([t^n]\)。
那么该复合指令的类型为 \([] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t^n]\)。
存储扩展¶
程序可以修改 存储 及其包含的实例。任何此类修改都必须遵守某些不变式,例如不删除已分配的实例或更改不可变定义。虽然这些不变式是 WebAssembly 指令 和 模块 执行语义固有的,但 宿主函数 并不会自动遵守它们。因此,必须将所需的不变式表述为对 调用 宿主函数的明确约束。只有当 嵌入器 确保这些约束时,健壮性才成立。
必要的约束由存储扩展的概念进行编码:当以下规则成立时,存储状态 \(S'\) 扩展状态 \(S\),记为 \(S \href{../appendix/properties.html#extend}{\preceq} S'\)。
注意
扩展并不意味着新存储是有效的,有效性在 上面 单独定义。
存储 \(S\)¶
\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}\) 的长度不能缩短。
\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{tables}}\) 的长度不能缩短。
\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{mems}}\) 的长度不能缩短。
\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{globals}}\) 的长度不能缩短。
\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{elems}}\) 的长度不能缩短。
\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{datas}}\) 的长度不能缩短。
对于原始 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}\) 中的每个 函数实例 \(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}_i\),新的函数实例必须是旧实例的 扩展。
对于原始 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{tables}}\) 中的每个 表格实例 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}_i\),新的表格实例必须是旧实例的 扩展。
对于原始 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{mems}}\) 中的每个 内存实例 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}_i\),新的内存实例必须是旧实例的 扩展。
对于原始 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{globals}}\) 中的每个 全局实例 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}_i\),新的全局实例必须是旧实例的 扩展。
对于原始 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{elems}}\) 中的每个 元素实例 \(\href{../exec/runtime.html#syntax-eleminst}{\mathit{eleminst}}_i\),新的元素实例必须是旧实例的 扩展。
对于原始 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{datas}}\) 中的每个 数据实例 \(\href{../exec/runtime.html#syntax-datainst}{\mathit{datainst}}_i\),新的数据实例必须是旧实例的 扩展。
函数实例 \(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}\)¶
函数实例必须保持不变。
表格实例 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}\)¶
表格类型 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}.\href{../exec/runtime.html#syntax-tableinst}{\mathsf{type}}\) 必须保持不变。
\(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}.\href{../exec/runtime.html#syntax-tableinst}{\mathsf{elem}}\) 的长度不能缩短。
内存实例 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}\)¶
内存类型 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}.\href{../exec/runtime.html#syntax-meminst}{\mathsf{type}}\) 必须保持不变。
\(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}.\href{../exec/runtime.html#syntax-meminst}{\mathsf{data}}\) 的长度不能缩短。
全局实例 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}\)¶
全局类型 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}.\href{../exec/runtime.html#syntax-globalinst}{\mathsf{type}}\) 必须保持不变。
令 \(\href{../syntax/types.html#syntax-mut}{\mathit{mut}}~t\) 为 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}.\href{../exec/runtime.html#syntax-globalinst}{\mathsf{type}}\) 的结构。
如果 \(\href{../syntax/types.html#syntax-mut}{\mathit{mut}}\) 是 \(\href{../syntax/types.html#syntax-mut}{\mathsf{const}}\),那么 值 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}.\href{../exec/runtime.html#syntax-globalinst}{\mathsf{value}}\) 必须保持不变。
元素实例 \(\href{../exec/runtime.html#syntax-eleminst}{\mathit{eleminst}}\)¶
向量 \(\href{../exec/runtime.html#syntax-eleminst}{\mathit{eleminst}}.\href{../exec/runtime.html#syntax-eleminst}{\mathsf{elem}}\) 必须保持不变或缩短到长度 0。
数据实例 \(\href{../exec/runtime.html#syntax-datainst}{\mathit{datainst}}\)¶
向量 \(\href{../exec/runtime.html#syntax-datainst}{\mathit{datainst}}.\href{../exec/runtime.html#syntax-datainst}{\mathsf{data}}\) 必须保持不变或缩短到长度 0。
定理¶
在 有效配置 的定义下,标准的健壮性定理成立。 [2] [3]
定理(保持)。 如果一个 配置 \(S;T\) 是 有效 的,具有 结果类型 \([t^\ast]\) (即,\(\href{../appendix/properties.html#valid-config}{\vdash} S;T : [t^\ast]\)),并且步骤到 \(S';T'\) (即,\(S;T \href{../exec/conventions.html#exec-notation}{\hookrightarrow} S';T'\)),那么 \(S';T'\) 是具有相同结果类型(即,\(\href{../appendix/properties.html#valid-config}{\vdash} S';T' : [t^\ast]\))的有效配置。此外,\(S'\) 是 \(S\) 的 扩展 (即,\(\href{../appendix/properties.html#extend-store}{\vdash} S \href{../appendix/properties.html#extend}{\preceq} S'\))。
一个终端 线程 是指其 指令 序列为 结果 的线程。终端配置是指其线程为终端的配置。
定理(进展)。 如果一个 配置 \(S;T\) 是 有效 的(即,\(\href{../appendix/properties.html#valid-config}{\vdash} S;T : [t^\ast]\) 对于某个 结果类型 \([t^\ast]\)),那么它要么是终端的,要么可以步骤到某个配置 \(S';T'\) (即,\(S;T \href{../exec/conventions.html#exec-notation}{\hookrightarrow} S';T'\))。
从保持和进展定理中,可以直接得出 WebAssembly 类型系统的健壮性。
推论(健壮性)。 如果一个 配置 \(S;T\) 是 有效 的(即,\(\href{../appendix/properties.html#valid-config}{\vdash} S;T : [t^\ast]\) 对于某个 结果类型 \([t^\ast]\)),那么它要么发散,要么经过有限次数的步骤到达一个终端配置 \(S';T'\) (即,\(S;T \href{../exec/conventions.html#exec-notation}{\hookrightarrow}^\ast S';T'\)),该终端配置是有效并且具有相同的结果类型(即,\(\href{../appendix/properties.html#valid-config}{\vdash} S';T' : [t^\ast]\)),并且 \(S'\) 是 \(S\) 的 扩展 (即,\(\href{../appendix/properties.html#extend-store}{\vdash} S \href{../appendix/properties.html#extend}{\preceq} S'\))。
换句话说,有效配置中的每个线程要么永远运行,要么陷入陷阱,要么以具有预期类型的结果终止。因此,给定一个 有效存储,由 实例化 或 调用 有效模块定义的任何计算都不会“崩溃”或以本规范中未涵盖的方式(错误)执行。