mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-06 07:38:24 +00:00
fixes 23827; Cyclic proc calls causes infinite memory usage in VM
This commit is contained in:
@@ -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`)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
18
tests/vm/tcyclic.nim
Normal 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("", "")
|
||||
Reference in New Issue
Block a user