--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityChecker.py Thu Feb 27 09:22:15 2025 +0100 +++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Security/SecurityChecker.py Thu Feb 27 14:42:39 2025 +0100 @@ -8,13 +8,14 @@ """ import collections -import copy + +from CodeStyleTopicChecker import CodeStyleTopicChecker from . import Checks from .SecurityNodeVisitor import SecurityNodeVisitor -class SecurityChecker: +class SecurityChecker(CodeStyleTopicChecker): """ Class implementing a checker for security issues. """ @@ -117,6 +118,7 @@ "S-801", "S-802", ] + Category = "S" def __init__(self, source, filename, tree, select, ignore, expected, repeat, args): """ @@ -139,43 +141,29 @@ @param args dictionary of arguments for the security checks @type dict """ - self.__select = tuple(select) - self.__ignore = tuple(ignore) - self.__expected = expected[:] - self.__repeat = repeat - self.__filename = filename - self.__source = source[:] - self.__tree = copy.deepcopy(tree) - self.__args = args - - # statistics counters - self.counters = {} - - # collection of detected errors - self.errors = [] + super().__init__( + SecurityChecker.Category, + source, + filename, + tree, + select, + ignore, + expected, + repeat, + args, + ) checkersWithCodes = Checks.generateCheckersDict() self.__checkers = collections.defaultdict(list) for checkType, checkersList in checkersWithCodes.items(): for checker, codes in checkersList: - if any(not (code and self.__ignoreCode(code)) for code in codes): + if any( + not (msgCode and self._ignoreCode(msgCode)) for msgCode in codes + ): self.__checkers[checkType].append(checker) - def __ignoreCode(self, code): - """ - Private method to check if the message code should be ignored. - - @param code message code to check for - @type str - @return flag indicating to ignore the given code - @rtype bool - """ - return code in self.__ignore or ( - code.startswith(self.__ignore) and not code.startswith(self.__select) - ) - - def reportError(self, lineNumber, offset, code, severity, confidence, *args): + def addError(self, lineNumber, offset, msgCode, severity, confidence, *args): """ Public method to record an issue. @@ -183,7 +171,7 @@ @type int @param offset position within line of the issue @type int - @param code message code + @param msgCode message code @type str @param severity severity code (H = high, M = medium, L = low, U = undefined) @@ -194,26 +182,26 @@ @param args arguments for the message @type list """ - if self.__ignoreCode(code): + if self._ignoreCode(msgCode): return - if code in self.counters: - self.counters[code] += 1 + if msgCode in self.counters: + self.counters[msgCode] += 1 else: - self.counters[code] = 1 + self.counters[msgCode] = 1 # Don't care about expected codes - if code in self.__expected: + if msgCode in self.expected: return - if code and (self.counters[code] == 1 or self.__repeat): + if msgCode and (self.counters[msgCode] == 1 or self.repeat): # record the issue with one based line number self.errors.append( { - "file": self.__filename, + "file": self.filename, "line": lineNumber + 1, "offset": offset, - "code": code, + "code": msgCode, "args": args, "severity": severity, "confidence": confidence, @@ -227,14 +215,14 @@ @return dictionary containing the configuration @rtype dict """ - return self.__args + return self.args def run(self): """ Public method to check the given source against security related conditions. """ - if not self.__filename: + if not self.filename: # don't do anything, if essential data is missing return @@ -243,7 +231,7 @@ return securityNodeVisitor = SecurityNodeVisitor( - self, self.__checkers, self.__filename, self.__source + self, self.__checkers, self.filename, self.source ) - securityNodeVisitor.generic_visit(self.__tree) + securityNodeVisitor.generic_visit(self.tree) securityNodeVisitor.checkFile()