Skip to content

Commit a3eee90

Browse files
committed
some fixes and add some last resort "timeout" check to prevent analyzer from getting stuck forever
1 parent 493061b commit a3eee90

File tree

7 files changed

+43
-11
lines changed

7 files changed

+43
-11
lines changed

nattlua/analyzer/analyzer.lua

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ do
144144
elseif node.kind == "postfix_expression_index" then
145145
local val = self:Assert(self:AnalyzeExpression(node.left))
146146
local obj = self:Assert(self:AnalyzeExpression(node.expression))
147+
147148
if not self:IsTypesystem() then
148149
val = self:GetFirstValue(val)
149150
obj = self:GetFirstValue(obj)
@@ -209,6 +210,7 @@ do
209210

210211
function META:AnalyzeExpression(node)
211212
self:PushCurrentExpression(node)
213+
self:CheckTimeout()
212214
local obj, err = self:AnalyzeRuntimeExpression(node)
213215
self:PopCurrentExpression()
214216

@@ -222,6 +224,37 @@ do
222224
node.scope = self:GetScope()
223225
return obj, err
224226
end
227+
228+
function META:CheckTimeout()
229+
self.check_count = (self.check_count or 0) + 1
230+
local count = self.check_count
231+
232+
if count < 90000 then return end
233+
234+
self.timeout = self.timeout or {}
235+
local node = self:GetCurrentStatement() or self:GetCurrentExpression()
236+
self.timeout[node] = (self.timeout[node] or 0) + 1
237+
238+
if count < 100000 then return end
239+
240+
local top = {}
241+
242+
for node, count in pairs(self.timeout) do
243+
if count > 5 then table.insert(top, {node = node, count = count}) end
244+
end
245+
246+
table.sort(top, function(a, b)
247+
return a.count > b.count
248+
end)
249+
250+
for i, info in ipairs(top) do
251+
if i > 10 then break end
252+
253+
self:Warning({info.node, " was crawled ", info.count, " times"})
254+
end
255+
256+
self:FatalError("too many iterations, stopping execution")
257+
end
225258
end
226259

227260
function META:OnDiagnostic() end

nattlua/analyzer/operators/binary.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ local function Binary(self, node, l, r, op)
241241
l = self:Assert(self:AnalyzeExpression(node.left))
242242
r = self:Assert(self:AnalyzeExpression(node.right))
243243
end
244+
244245
self:TrackUpvalue(l)
245246
self:TrackUpvalue(r)
246247

nattlua/analyzer/operators/newindex.lua

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,7 @@ return {
124124
end
125125

126126
function META:NewIndexOperator(obj, key, val, raw)
127-
if obj.Type == "any" then
128-
return true
129-
end
127+
if obj.Type == "any" then return true end
130128

131129
if
132130
val.Type == "function" and
@@ -164,9 +162,7 @@ return {
164162
ok, err = obj:Set(key, val)
165163
end
166164

167-
if not ok then
168-
self:Error(err)
169-
end
165+
if not ok then self:Error(err) end
170166
end
171167
end,
172168
}

nattlua/analyzer/statements/assignment.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ return {
143143
-- local a: >>number<< = 1
144144
if exp_key.type_expression then
145145
self:PushAnalyzerEnvironment("typesystem")
146-
local contract = self:AnalyzeExpression(exp_key.type_expression)
146+
local contract = self:Assert(self:AnalyzeExpression(exp_key.type_expression))
147147
self:PopAnalyzerEnvironment()
148148

149149
if right[left_pos] then
@@ -237,7 +237,7 @@ return {
237237
else
238238
-- TODO: refactor out to mutation assignment?
239239
-- index assignment: foo[a] = 1
240-
local obj = self:AnalyzeExpression(exp_key.left)
240+
local obj = self:Assert(self:AnalyzeExpression(exp_key.left))
241241
self:ClearTracked()
242242

243243
if self:IsRuntime() then key = self:GetFirstValue(key) or Nil() end

nattlua/compiler.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ function META:OnDiagnostic(code, msg, severity, start, stop, node, ...)
100100
msg = "\x1b[0;31m" .. msg .. "\x1b[0m"
101101
elseif severity == "warning" then
102102
msg = "\x1b[0;33m" .. msg .. "\x1b[0m"
103+
elseif severity == "fatal" then
104+
msg = "\x1b[0;35m" .. msg .. "\x1b[0m"
103105
end
104106

105107
if not _G.TEST then

test/tests/nattlua/analyzer/complex/ffibuild.nlua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
do return end
1+
do
2+
return
3+
end
24

35
do
46
_G[jit.os:upper()] = true

test/tests/nattlua/analyzer/lua.lua

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,8 @@ analyze("attest.equal(((1 or false) and true) or false, true)")
241241

242242
do --- allcases
243243
local basiccases = {
244-
{"nil", nil},
245244
{"false", false},
246245
{"true", true},
247-
{"10", 10},
248246
}
249247
local mem = {basiccases} -- for memoization
250248
local function allcases(n)

0 commit comments

Comments
 (0)