@@ -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 )
12831302def _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
13101322def _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