checker: limit recursion in Checker.ensure_type_exists/2 to 40 levels (it is usually 4 or less) (#21734)

This commit is contained in:
Delyan Angelov 2024-06-26 06:50:46 +03:00 committed by GitHub
parent 8466c6c03d
commit 5f33946ef0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -18,6 +18,7 @@ import v.comptime
// prevent stack overflows by restricting too deep recursion:
const expr_level_cutoff_limit = 40
const stmt_level_cutoff_limit = 40
const type_level_cutoff_limit = 40 // it is very rarely deeper than 4
const iface_level_cutoff_limit = 100
const generic_fn_cutoff_limit_per_fn = 10_000 // how many times post_process_generic_fns, can visit the same function before bailing out
@ -101,6 +102,7 @@ mut:
// increases for `x := optfn() or { statement_list3 }`;
// files []ast.File
expr_level int // to avoid infinite recursion segfaults due to compiler bugs
type_level int // to avoid infinite recursion segfaults due to compiler bugs in ensure_type_exists
ensure_generic_type_level int // to avoid infinite recursion segfaults in ensure_generic_type_specify_type_names
cur_orm_ts ast.TypeSymbol
cur_anon_fn &ast.AnonFn = unsafe { nil }
@ -4947,6 +4949,15 @@ fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) bool {
c.error('unknown type', pos)
return false
}
c.type_level++
defer {
c.type_level--
}
if c.type_level > checker.type_level_cutoff_limit {
c.error('checker: too many levels of Checker.ensure_type_exists calls: ${c.type_level}, probably due to a self referencing type',
pos)
return false
}
sym := c.table.sym(typ)
if !c.is_builtin_mod && sym.kind == .struct_ && !sym.is_pub && sym.mod != c.mod {
c.error('struct `${sym.name}` was declared as private to module `${sym.mod}`, so it can not be used inside module `${c.mod}`',