Skip to content

Commit 3fa7e1b

Browse files
SYN-11870: Share scope resolution between S015 and S016
1 parent edc58d4 commit 3fa7e1b

1 file changed

Lines changed: 26 additions & 22 deletions

File tree

‎synapse/lib/stormlint.py‎

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ def _ruleTryCast(ctx):
12511251
if ctx.callPath(call) == ('lib', 'cast'):
12521252
ctx.report(call, 'Use $lib.trycast() instead of $lib.cast() in a try block.')
12531253

1254-
def _getBinds(ctx, node, paths=(('lib', 'import'),)):
1254+
def _getBinds(ctx, node, paths):
12551255
'''
12561256
Return the names a scope assigns, and the names it assigns from a call to one of the paths.
12571257
'''
@@ -1279,6 +1279,25 @@ def _argName(arg):
12791279

12801280
return arg.valu
12811281

1282+
def _getScopes(ctx, paths):
1283+
'''
1284+
Return a (node, binds) pair for the module scope and then for each function scope.
1285+
1286+
binds are the names in scope which are assigned from a call to one of the paths. A function
1287+
sees the module binds it does not assign or take as a parameter.
1288+
'''
1289+
_, modbinds = _getBinds(ctx, ctx.query, paths)
1290+
1291+
scopes = [(ctx.query, modbinds)]
1292+
for func in ctx.walk(s_ast.Function):
1293+
1294+
names, binds = _getBinds(ctx, func.kids[2], paths)
1295+
names.update(_argName(arg) for arg in func.kids[1].kids)
1296+
binds.update(modbinds - names)
1297+
scopes.append((func.kids[2], binds))
1298+
1299+
return scopes
1300+
12821301
@rule('S015', 'return-import', 'medium', default=False)
12831302
def _ruleReturnImport(ctx):
12841303
'''
@@ -1288,15 +1307,8 @@ def _ruleReturnImport(ctx):
12881307
12891308
This rule is off by default. Turn it on with enable.
12901309
'''
1291-
_, modimports = _getBinds(ctx, ctx.query)
1292-
1293-
for func in ctx.walk(s_ast.Function):
1294-
1295-
names, imports = _getBinds(ctx, func.kids[2])
1296-
names.update(_argName(arg) for arg in func.kids[1].kids)
1297-
imports.update(modimports - names)
1298-
1299-
for node in ctx.walk(s_ast.Return, node=func.kids[2], skip=s_ast.Function):
1310+
for scope, imports in _getScopes(ctx, (('lib', 'import'),))[1:]:
1311+
for node in ctx.walk(s_ast.Return, node=scope, skip=s_ast.Function):
13001312

13011313
if not node.kids:
13021314
continue
@@ -1309,7 +1321,9 @@ def _ruleReturnImport(ctx):
13091321

13101322
def _getLeaks(ctx, node, names):
13111323
'''
1312-
Yield (node, name) for each use in an output argument of a response which holds the request headers.
1324+
Yield (node, name) for each part of a print argument which exposes the request headers: a variable
1325+
in names, used whole or through its request, request_headers or history member, or a direct call
1326+
to one of the httpcalls, for which name is None.
13131327
'''
13141328
if isinstance(node, s_ast.FuncCall):
13151329
if ctx.callPath(node) in httpcalls:
@@ -1346,17 +1360,7 @@ def _rulePrintHttpResp(ctx):
13461360
13471361
This rule is off by default. Turn it on with enable.
13481362
'''
1349-
_, modresps = _getBinds(ctx, ctx.query, paths=httpcalls)
1350-
1351-
scopes = [(ctx.query, modresps)]
1352-
for func in ctx.walk(s_ast.Function):
1353-
1354-
names, resps = _getBinds(ctx, func.kids[2], paths=httpcalls)
1355-
names.update(_argName(arg) for arg in func.kids[1].kids)
1356-
resps.update(modresps - names)
1357-
scopes.append((func.kids[2], resps))
1358-
1359-
for scope, resps in scopes:
1363+
for scope, resps in _getScopes(ctx, httpcalls):
13601364
for call in ctx.walk(s_ast.FuncCall, node=scope, skip=s_ast.Function):
13611365

13621366
if ctx.callPath(call) not in printcalls:

0 commit comments

Comments
 (0)