我尝试了一些JSON模式验证器,但有些失败了,但问题是弄清楚验证器使用多少内存导致它被阻塞并被杀死。
事实证明,我们可以在JSON模式中实现有限状态机。为此,FSM节点是对象模式,FSM边是包含在anyOf
中的一组JSON指针。整个过程相当简单,但能够做到这一点有一些结果:如果我们创建一个需要2 ^ N 时间或内存的FSM(分别是深度优先搜索或广度优先搜索) )给定一个带有 N 定义的JSON模式和一些要验证的输入?
因此,让我们创建一个带有 N 定义的JSON模式,以在两个符号a
和b
的字母表上实现非确定性有限状态机(NFA)。我们需要做的就是对正则表达式进行编码
(a{N}|a(a|b+){0,N-1}b)*x
,其中x
表示结束。在最坏的情况下,该正则表达式的NFA需要2 ^ N 时间来匹配文本或2 ^ N 存储器(例如,当转换为确定性有限状态机时)。现在请注意,abbx
这个词可以用JSON指针a/b/b/x
表示,它在JSON中等同于{"a":{"b":{"b":{"x":true}}}}
。
要将此NFA编码为架构,我们首先添加状态“0”的定义:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/0",
"definitions": {
"0": {
"type": "object",
"properties": {
"a": { "$ref": "#/definitions/1" },
"x": { "type": "boolean" }
},
"additionalProperties": false
},
然后我们将每个状态<DEF>
的 N -1定义添加到<DEF>
枚举“1”,“2”,“3”,...的模式中。 。“ N -1”:
"<DEF>": {
"type": "object",
"properties": {
"a": { "$ref": "#/definitions/<DEF>+1" },
"b": {
"anyOf": [
{ "$ref": "#/definitions/0" },
{ "$ref": "#/definitions/<DEF>" }
]
}
},
"additionalProperties": false
},
当<DEF>
等于 N -1时,“<DEF>
+ 1”回绕到“0”。
两个字母的字母表中的“NFA”具有 N 状态,只有一个首字母和一个 最终状态。等效的最小DFA具有2 ^ N (2 <功率 N )状态。
这意味着在最坏的情况下,使用此架构的验证器必须花费2 ^ N 时间或使用2 ^ N 内存“cells”来验证输入。
我不知道这个逻辑可能出错的地方,除非验证者采用快捷方式来近似有效性检查。
我找到了this here。
答案 0 :(得分:1)
我认为原则上你是对的。我对你所描述的模式构造并不是100%肯定,但理论上应该可以构造一个需要^ N时间或空间的模式,完全是出于你描述的原因。
实际上,大多数架构处理器可能只是尝试递归验证anyOf
。那么,这将是指数时间。