fixes 23827; Cyclic proc calls causes infinite memory usage in VM

This commit is contained in:
ringabout
2024-07-12 22:10:11 +08:00
parent 570deb10d3
commit ca7821bea3
5 changed files with 25 additions and 6 deletions

View File

@@ -41,7 +41,7 @@ type
TNodeKinds* = set[TNodeKind]
type
TSymFlag* = enum # 52 flags!
TSymFlag* = enum # 53 flags!
sfUsed, # read access of sym (for warnings) or simply used
sfExported, # symbol is exported from module
sfFromGeneric, # symbol is instantiation of a generic; this is needed
@@ -52,6 +52,7 @@ type
sfForward, # symbol is forward declared
sfWasForwarded, # symbol had a forward declaration
# (implies it's too dangerous to patch its type signature)
sfNosinks, # symbol has a `nosinks` pragma
sfImportc, # symbol is external; imported
sfExportc, # symbol is exported (under a specified name)
sfMangleCpp, # mangle as cpp (combines with `sfExportc`)

View File

@@ -1036,7 +1036,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
incl(sym.flags, sfGeneratedOp)
of wNosinks:
noVal(c, it)
incl(sym.flags, sfWasForwarded)
incl(sym.flags, sfNosinks)
of wDynlib:
processDynLib(c, it, sym)
of wCompilerProc, wCore:

View File

@@ -28,7 +28,7 @@ proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNod
arg.sym.typ.kind notin {tyVar, tySink, tyOwned}:
# Watch out: cannot do this inference for procs with forward
# declarations.
if sfWasForwarded notin owner.flags:
if {sfWasForwarded, sfNosinks} * owner.flags == {}:
let argType = arg.sym.typ
let sinkType = newType(tySink, idgen, owner)
@@ -43,9 +43,9 @@ proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNod
#message(config, arg.info, warnUser,
# ("turned '$1' to a sink parameter") % [$arg])
#echo config $ arg.info, " turned into a sink parameter ", arg.sym.name.s
elif sfWasForwarded notin arg.sym.flags:
elif {sfWasForwarded, sfNosinks} * arg.sym.flags == {}:
# we only report every potential 'sink' parameter only once:
incl arg.sym.flags, sfWasForwarded
incl arg.sym.flags, sfNosinks
message(config, arg.info, hintPerformance,
"could not turn '$1' to a sink parameter" % [arg.sym.name.s])
#echo config $ arg.info, " candidate for a sink parameter here"

View File

@@ -1559,7 +1559,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
elif s.kind == skParam and s.typ.kind == tyTypeDesc: discard
else: cannotEval(c, n)
elif s.kind in {skProc, skFunc, skConverter, skMethod,
skIterator} and sfForward in s.flags:
skIterator} and sfWasForwarded in s.flags:
cannotEval(c, n)
template needsAdditionalCopy(n): untyped =

18
tests/vm/tcyclic.nim Normal file
View File

@@ -0,0 +1,18 @@
discard """
errormsg: "cannot evaluate at compile time: error"
"""
static: # bug #23827
# Forward-declaring procedure (let's call this proc "A")
proc error() {.raises: [].}
# called in another function (let's call this proc "B")
proc env(key: string, default: string = ""): string {.raises: [].} =
error()
# A used before its implmentation
# removing this line fixes the issue
let DESTDIR = env("", "")
# later, A's implementation uses B
proc error() = discard env("", "")