Skip to content

Commit fc52f4c

Browse files
committed
add some call depth and mutation count guards to prevent hanging
1 parent 3b3462c commit fc52f4c

File tree

7 files changed

+42
-5
lines changed

7 files changed

+42
-5
lines changed

nattlua/analyzer/base/error_handling.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ return function(META)
3030

3131
return ok, err, ...
3232
end
33+
34+
function META:AssertWarning(ok, err, ...)
35+
if not ok then
36+
self:Warning(err)
37+
return Any()
38+
end
39+
40+
return ok, err, ...
41+
end
3342

3443
function META:AssertWithNode(node, ok, err, ...)
3544
if not ok then

nattlua/analyzer/base/scopes.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ return function(META)
137137
return self:Error(type_errors.const_assignment(key))
138138
end
139139

140-
if not self:MutateUpvalue(upvalue, val) then upvalue:SetValue(val) end
140+
self:MutateUpvalue(upvalue, val)
141+
142+
upvalue:SetValue(val)
141143

142144
return upvalue
143145
end

nattlua/analyzer/base/upvalue.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local class = require("nattlua.other.class")
22
local mutation_solver = require("nattlua.analyzer.mutation_solver")
3+
local type_errors = require("nattlua.types.error_messages")
34
local tostring = _G.tostring
45
local assert = _G.assert
56
local table_insert = _G.table.insert
@@ -51,9 +52,14 @@ do
5152
function META:Mutate(val, scope, from_tracking)
5253
val:SetUpvalue(self)
5354
self.Mutations = self.Mutations or {}
55+
56+
if self.Mutations[100] then return false, type_errors.too_many_mutations() end
57+
5458
table_insert(self.Mutations, {scope = scope, value = val, from_tracking = from_tracking})
5559

5660
if from_tracking then scope:AddTrackedObject(self) end
61+
62+
return true
5763
end
5864

5965
function META:ClearMutations()

nattlua/analyzer/control_flow.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,13 @@ return function(META)
268268
end
269269
end
270270

271+
if #self:GetCallStack() > 100 or debug.getinfo(500, "") then
272+
local len = 501
273+
while debug.getinfo(len, "") do len = len + 1 end
274+
self:Error(type_errors.analyzer_callstack_too_deep(#self:GetCallStack(), len))
275+
return Tuple():AddRemainder(Tuple({Any()}):SetRepeat(math.huge))
276+
end
277+
271278
self:PushContextValue(
272279
"call_stack",
273280
{

nattlua/analyzer/mutation_tracking.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ return function(META)
6565
end
6666
end
6767

68-
tbl:Mutate(key, val, scope, from_tracking)
68+
self:AssertWarning(tbl:Mutate(key, val, scope, from_tracking))
6969
end
7070

7171
function META:GetMutatedUpvalue(upvalue)
@@ -83,7 +83,7 @@ return function(META)
8383
end
8484
end
8585

86-
upvalue:Mutate(val, scope, from_tracking)
86+
self:AssertWarning(upvalue:Mutate(val, scope, from_tracking))
8787
end
8888

8989
function META:ClearScopedTrackedObjects(scope)

nattlua/types/error_messages.lua

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,4 +296,13 @@ function type_errors.plain_error(msg--[[#: any]])--[[#: Reason]]
296296
return {msg}
297297
end
298298

299+
do
300+
function type_errors.analyzer_callstack_too_deep(len1, len2)
301+
return {"call stack is too deep. ", len1, " analyzer call frames and ", len2, " lua call stack frames "}
302+
end
303+
304+
function type_errors.too_many_mutations()
305+
return {"too many mutations"}
306+
end
307+
end
299308
return type_errors

nattlua/types/table.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,13 +1065,17 @@ do
10651065

10661066
function META:Mutate(key, val, scope, from_tracking)
10671067
local hash = key:GetHashForMutationTracking()
1068-
1069-
if hash == nil then return end
1068+
if hash == nil then return true end
10701069

10711070
initialize_table_mutation_tracker(self, scope, key, hash)
1071+
1072+
if #self.mutations[hash] > 100 then return false, type_errors.too_many_mutations() end
1073+
10721074
table.insert(self.mutations[hash], {scope = scope, value = val, from_tracking = from_tracking, key = key})
10731075

10741076
if from_tracking then scope:AddTrackedObject(self) end
1077+
1078+
return true
10751079
end
10761080

10771081
function META:ClearMutations()

0 commit comments

Comments
 (0)