--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityNodeVisitor.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityNodeVisitor.py Wed Jul 13 14:55:47 2022 +0200 @@ -17,10 +17,11 @@ """ Class implementing an AST node visitor for security checks. """ + def __init__(self, checker, secCheckers, filename): """ Constructor - + @param checker reference to the main security checker object @type SecurityChecker @param secCheckers dictionary containing the available checker routines @@ -30,7 +31,7 @@ """ self.__checker = checker self.__securityCheckers = secCheckers - + self.seen = 0 self.depth = 0 self.filename = filename @@ -42,97 +43,97 @@ self.namespace = SecurityUtils.getModuleQualnameFromPath(filename) except SecurityUtils.InvalidModulePath: self.namespace = "" - + def __runChecks(self, checkType): """ Private method to run all enabled checks for a given check type. - + @param checkType type of checks to be run @type str """ if checkType in self.__securityCheckers: for check in self.__securityCheckers[checkType]: - check(self.__checker.reportError, - SecurityContext(self.__context), - self.__checker.getConfig()) - + check( + self.__checker.reportError, + SecurityContext(self.__context), + self.__checker.getConfig(), + ) + def visit_ClassDef(self, node): """ Public method defining a visitor for AST ClassDef nodes. - + Add class name to current namespace for all descendants. - + @param node reference to the node being inspected @type ast.ClassDef """ # For all child nodes, add this class name to current namespace - self.namespace = SecurityUtils.namespacePathJoin( - self.namespace, node.name) - + self.namespace = SecurityUtils.namespacePathJoin(self.namespace, node.name) + def visit_FunctionDef(self, node): """ Public method defining a visitor for AST FunctionDef nodes. - + @param node reference to the node being inspected @type ast.FunctionDef """ self.__visitFunctionDefinition(node) - + def visit_AsyncFunctionDef(self, node): """ Public method defining a visitor for AST AsyncFunctionDef nodes. - + @param node reference to the node being inspected @type ast.AsyncFunctionDef """ self.__visitFunctionDefinition(node) - + def __visitFunctionDefinition(self, node): """ Private method defining a visitor for AST FunctionDef and AsyncFunctionDef nodes. - + Add relevant information about the node to the context for use in tests which inspect function definitions. Add the function name to the current namespace for all descendants. - + @param node reference to the node being inspected @type ast.FunctionDef, ast.AsyncFunctionDef """ - self.__context['function'] = node + self.__context["function"] = node qualname = SecurityUtils.namespacePathJoin(self.namespace, node.name) - name = qualname.split('.')[-1] - self.__context['qualname'] = qualname - self.__context['name'] = name + name = qualname.split(".")[-1] + self.__context["qualname"] = qualname + self.__context["name"] = name # For all child nodes and any tests run, add this function name to # current namespace - self.namespace = SecurityUtils.namespacePathJoin( - self.namespace, node.name) - + self.namespace = SecurityUtils.namespacePathJoin(self.namespace, node.name) + self.__runChecks("FunctionDef") - + def visit_Call(self, node): """ Public method defining a visitor for AST Call nodes. - + Add relevant information about the node to the context for use in tests which inspect function calls. - + @param node reference to the node being inspected @type ast.Call """ - self.__context['call'] = node + self.__context["call"] = node qualname = SecurityUtils.getCallName(node, self.import_aliases) - name = qualname.split('.')[-1] - self.__context['qualname'] = qualname - self.__context['name'] = name + name = qualname.split(".")[-1] + self.__context["qualname"] = qualname + self.__context["name"] = name self.__runChecks("Call") - + def visit_Import(self, node): """ Public method defining a visitor for AST Import nodes. - + @param node reference to the node being inspected @type ast.Import """ @@ -140,16 +141,16 @@ if nodename.asname: self.import_aliases[nodename.asname] = nodename.name self.imports.add(nodename.name) - self.__context['module'] = nodename.name + self.__context["module"] = nodename.name self.__runChecks("Import") - + def visit_ImportFrom(self, node): """ Public method defining a visitor for AST Import nodes. - + This adds relevant information about the node to the context for use in tests which inspect imports. - + @param node reference to the node being inspected @type ast.ImportFrom """ @@ -157,30 +158,27 @@ if module is None: self.visit_Import(node) return - + for nodename in node.names: if nodename.asname: - self.import_aliases[nodename.asname] = ( - module + "." + nodename.name - ) + self.import_aliases[nodename.asname] = module + "." + nodename.name else: # Even if import is not aliased we need an entry that maps # name to module.name. For example, with 'from a import b' # b should be aliased to the qualified name a.b - self.import_aliases[nodename.name] = ( - module + '.' + nodename.name) + self.import_aliases[nodename.name] = module + "." + nodename.name self.imports.add(module + "." + nodename.name) - self.__context['module'] = module - self.__context['name'] = nodename.name + self.__context["module"] = module + self.__context["name"] = nodename.name self.__runChecks("ImportFrom") - + def visit_Constant(self, node): """ Public method defining a visitor for Constant nodes. - + This calls the appropriate method for the node type. It maintains compatibility with <3.6 and 3.8+ - + @param node reference to the node being inspected @type ast.Constant """ @@ -192,16 +190,16 @@ def visit_Str(self, node): """ Public method defining a visitor for String nodes. - + This adds relevant information about node to the context for use in tests which inspect strings. - + @param node reference to the node being inspected @type ast.Str """ - self.__context['str'] = node.s + self.__context["str"] = node.s if not isinstance(node._securityParent, ast.Expr): # docstring - self.__context['linerange'] = SecurityUtils.linerange_fix( + self.__context["linerange"] = SecurityUtils.linerange_fix( node._securityParent ) self.__runChecks("Str") @@ -209,64 +207,64 @@ def visit_Bytes(self, node): """ Public method defining a visitor for Bytes nodes. - + This adds relevant information about node to the context for use in tests which inspect strings. - + @param node reference to the node being inspected @type ast.Bytes """ - self.__context['bytes'] = node.s + self.__context["bytes"] = node.s if not isinstance(node._securityParent, ast.Expr): # docstring - self.__context['linerange'] = SecurityUtils.linerange_fix( + self.__context["linerange"] = SecurityUtils.linerange_fix( node._securityParent ) self.__runChecks("Bytes") - + def __preVisit(self, node): """ Private method to set up a context for the visit method. - + @param node node to base the context on @type ast.AST @return flag indicating to visit the node @rtype bool """ self.__context = {} - self.__context['imports'] = self.imports - self.__context['import_aliases'] = self.import_aliases - - if hasattr(node, 'lineno'): - self.__context['lineno'] = node.lineno - - self.__context['node'] = node - self.__context['linerange'] = SecurityUtils.linerange_fix(node) - self.__context['filename'] = self.filename + self.__context["imports"] = self.imports + self.__context["import_aliases"] = self.import_aliases + + if hasattr(node, "lineno"): + self.__context["lineno"] = node.lineno + + self.__context["node"] = node + self.__context["linerange"] = SecurityUtils.linerange_fix(node) + self.__context["filename"] = self.filename self.seen += 1 self.depth += 1 - + return True - + def visit(self, node): """ Public method to inspected an AST node. - + @param node AST node to be inspected @type ast.AST """ name = node.__class__.__name__ - method = 'visit_' + name + method = "visit_" + name visitor = getattr(self, method, None) if visitor is not None: visitor(node) else: self.__runChecks(name) - + def __postVisit(self, node): """ Private method to clean up after a node was visited. - + @param node AST node that was visited @type ast.AST """ @@ -274,13 +272,12 @@ # Clean up post-recursion stuff that gets setup in the visit methods # for these node types. if isinstance(node, (ast.FunctionDef, ast.ClassDef)): - self.namespace = SecurityUtils.namespacePathSplit( - self.namespace)[0] - + self.namespace = SecurityUtils.namespacePathSplit(self.namespace)[0] + def generic_visit(self, node): """ Public method to drive the node visitor. - + @param node node to be inspected @type ast.AST """