opa
opa copied to clipboard
Stack overflow in type checker given recursive ref in schema
This came up when trying to make Regal commands make use of a schema I wrote for the AST. A few elements of that schema are recursive by necessity, like else clauses in rules, which are essentially references to other "rules", which may contain other else clauses, and so on. Reducing it to a minimal example:
schema.json
{
"$ref": "#/$defs/foo",
"$defs": {
"foo": {
"type": "object",
"properties": {
"foo": {
"$ref": "#/$defs/foo"
}
}
}
}
}
policy.rego
package p
allow := input.foo
❯ opa eval -d policy.rego -s schema.json data.p
runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0x14020700380 stack=[0x14020700000, 0x14040700000]
fatal error: stack overflow
runtime stack:
... long stack trace here ...
This prevents type checking for these type of attributes. As a temporary workaround, I can create something like "else1", "else2", "else3" types, but... whatever number I come up with, I'm sure some AST will have one more 😄
It's worth noting that I tried the same schema using the json.match_schema, but luckily it did not have this problem.
Spotted in the wild https://github.com/infracost/infracost/blob/032cba294b9c34184eb7616697f0f87d0378e5b8/cmd/jsonschema/main.go#L72
We've experienced this one as well (or our users have reported). See this for details.
Any suggestions how we can get around it? Or if something is in the works already?
Hi @simar7 👋 Nothing in the works. If someone has the bandwidth to tackle this, that'd be great.
As for a workaround, that would be to remove the recursive reference in the schema by setting the type to a generic object, or whatever the type is valid. We do this in Regal in some places, like here, where the else clause is recursive (as it may contain other else clauses, which may contain other else clauses...).
Obviously, that means this element won't be fully covered by the schema checks, but that's likely preferable over the stack overflow error.