def start_xml_file(self, file): tree = ET.ElementTree(file=open_source_file(file.get_path())) root = tree.getroot() if root.tag != 'mapper': pass else: log.info('Scanning MyBatis3 file: %s' % file.get_path()) typeAliases = TypeAliases.parse(root) resultMaps = ResultMaps.parse(root, typeAliases) sql_queries = CommonParsing.get_sql_queries(root) statement_queries = CommonParsing.get_statement_queries(root) CommonParsing.add_sqlnamedquery(statement_queries, sql_queries, resultMaps, typeAliases, file, root.attrib['namespace']) procedure_queries = CommonParsing.get_procedure_queries(root) CommonParsing.add_sqlnamedquery(procedure_queries, sql_queries, resultMaps, typeAliases, file, root.attrib['namespace']) select_queries = CommonParsing.get_select_queries(root) CommonParsing.add_sqlnamedquery(select_queries, sql_queries, resultMaps, typeAliases, file, root.attrib['namespace']) insert_queries = CommonParsing.get_insert_queries(root) CommonParsing.add_sqlnamedquery(insert_queries, sql_queries, resultMaps, typeAliases, file, root.attrib['namespace']) update_queries = CommonParsing.get_update_queries(root) CommonParsing.add_sqlnamedquery(update_queries, sql_queries, resultMaps, typeAliases, file, root.attrib['namespace']) delete_queries = CommonParsing.get_delete_queries(root) CommonParsing.add_sqlnamedquery(delete_queries, sql_queries, resultMaps, typeAliases, file, root.attrib['namespace'])
def start_file(self, file): # Extension point : each file if not self.active: return # no need to do something filepath = file.get_path() _, ext = os.path.splitext(filepath) if not ext in self.extensions: return log.debug('\t JasperReportAnalysisExtension start_file %s: %s)' % (os.path.basename(filepath), filepath)) try: with open_source_file(filepath) as f: self.nb_jrxml_files += 1 list_reports = parse(f.read(), filepath, log) for report in list_reports: report.save(file) self.nb_reports += 1 self.nb_sqlqueries += len(report.list_querystrings) except: log.warning('Issue analyzing file ' + traceback.format_exc())
def scan_file_CWE_482(application, pfile, fileType): # Author : PMB # last modification date: 27/3/2017 # Description: CWE_482: Comparing instead of Assigning # Languages : C/C++ # Property : CWEforFDA_CustomMetrics_C_CPP.CWE482violationCPP - CatID=2002000 PropID=2002012 SubID=2002262 QRID=2002574 # NOTE: The code uses an operator for comparison when the intention was to perform an assignment. # In many languages, the compare statement is very close in appearance to the assignment statement; they are often confused. # nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False #SCS msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-482 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-482 : Starting scan_file_CWE_482 > " + str(pfile.name)) # search #pathSrc="(^[ \ta-zA-Z0-9_\s\*]+)(==)([a-zA-Z0-9\s]+)" pathSrc="[^\s\t]*(\**[a-zA-Z0-9_]+(\s*\[\s*[a-zA-Z0-9_]*\s*\]\s*)?)\s*==\s*([a-zA-Z0-9\s]+)\s*(\,|\;|\.)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End #SCS nBytes = nBytes + len(line) # Get the most specific object containing the line obj = pfile.find_most_specific_object(current_line, 1) result = re.finditer(pathSrc, line) if not result is None: for p in result: #logging.debug("Found Stmt > %s at line %s, col. %s", p.group(), current_line, p.start()+1) # Set a bookmark for violation and save violation bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) #logging.debug("CWE-482 : Detected violation > %s at line %s, col. %s", p.group(), current_line, p.start()+1) try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE482violationCPP',bk) except: local_library.cwefdaLoggerWarning("CWE-482 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation +=1 except FileNotFoundError: logging.error("CWE-482 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-482 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE-482 : END scan_file_CWE_482 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "CWE-482",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "CWE-482",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation14_1_5(application, pfile, fileType): # Description: SPDBviolation14_1_5: Memory allocation with malloc should be checked with NULL skipFirstPattern = 0 skipSecontPattern = 0 nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False # SCS msecs = local_library.millis() nBytes = 0 logging.info( "14_1_5 : -------------------------------------------------------------------------" ) logging.info("14_1_5 : Starting scan_file_SPDBviolation14_1_5 > " + str(pfile.name)) # search "pthread_mutex_lock" pathSrc = "[\t*|\s*]free\s*\((.*)(?=\))" open1 = "(" close1 = ")" patNullify = "\s*=\s*NULL\s*;" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End # SCS nBytes = nBytes + len(line) if skipFirstPattern == 0: # Get the most specific object containing the line result = re.finditer(pathSrc, line) if not result is None: # print( lines ) # logging.error( lines ) for p in result: # lines=f.readlines(current_line) logging.error("Currently processing %s", line) logging.error("Freed memory %s", p.group(1)) module_line = linecache.getline( pfile.get_path(), current_line + 1) logging.error("%s", module_line) if module_line.__eq__("\n"): module_line = linecache.getline( pfile.get_path(), current_line + 2) markFreed(pfile, current_line, p, module_line) # patNullifyConstruct = open1 + p.group(1) + close1 + patNullify # resNullify = re.findall(patNullifyConstruct, module_line) # logging.error("Pattern %s, String %s", patNullifyConstruct, module_line) # # if resNullify: # print("MEMORY is freed - True %s", module_line) # else: # print("MEMORY is NOT freed - VIOLATION %s", module_line) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) # pfile.save_violation('SPDB_CustomMetrics_C.SPDBviolation14_1_5', bk) else: markFreed(pfile, current_line, p, module_line) # patNullifyConstruct = open1 + p.group(1) + close1 + patNullify # resNullify = re.findall(patNullifyConstruct, module_line) # logging.error("Pattern %s, String %s", patNullifyConstruct, module_line) # # if resNullify: # print("MEMORY is freed - True %s", module_line) # else: # print("MEMORY is NOT freed - VIOLATION %s", module_line) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) # pfile.save_violation('SPDB_CustomMetrics_C.SPDBviolation14_1_5', bk) else: nbViolation += 1 except FileNotFoundError: logging.error("SPDBviolation14_1_5 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("SPDBviolation14_1_5 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.error( "SPDBviolation14_1_5 : END scan_file_SPDBviolation14_1_5 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation14_1_5", nbViolation, nbNAViolation update_counts(tc) # Extra log t = "SPDBviolation14_1_5", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation12_2_5(application, pfile, fileType): # Avoid return Pointer, because memory exists and is destroyed automatically at the end of the function body # Description: scan_file_SPDBviolation12_2_5 # NOTE # As the rule is widely general and largely semantic, it is tailored only on specific patterns. # It simply finds all function calls which are not assigned to vars. # nbViolation = 0 nbNAViolation = 0 msecs = local_library.millis() nBytes = 0 logging.info( "scan_file_SPDBviolation12_2_5 : -------------------------------------------------------------------------" ) logging.info("scan_file_SPDBviolation12_2_5 : Starting > " + str(pfile.name)) patFunCall = "(float|int|char|bool)\s*\*\s*([\w]*)(\(.*)(?=)" # patFunCall = "\b(?:(?:int\s*|float\s*|char\s*|bool)+)(?:\s+\*?\*?\s*)([a-zA-Z0-9_]*)\s*(\[.*?\])" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[^,\s][^\,]*[^,\s]*)\s*[;,*=)]" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[a-z]*[A-Z]*[0-9]*)\s*\s*[;,=)]" # patFunCall = "\b(?:(?:auto\s*|const\s*|unsigned\s*|signed\s*|register\s*|volatile\s*|static\s*|void\s*|short\s*|long\s*|char\s*|int\s*|float\s*|double\s*|_Bool\s*|complex\s*)+)(?:\s+\*?\*?\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*[\[;,=)]" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False with open_source_file(pfile.get_path()) as f: if (pfile.get_path().endswith('libtypeb.c') or pfile.get_path().endswith('win.c') or pfile.get_path().endswith('win32s.c') or pfile.get_path().endswith('servdll.c')): logging.error("Check this break point======>") # current line number current_line = 0 for line in f: # Line of code # logging.error("Current line %s", line) current_line += 1 try: resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get function call patterns result = re.finditer(patFunCall, line) if (not result is None): for p in result: logging.info( "scan_file_SPDBviolation12_2_5::Result is: %s %s", pfile, line) try: # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) bk = Bookmark(pfile, current_line, 1, current_line, -1) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation12_2_5', bk) logging.info( "scan_file_SPDBviolation12_2_5 :: [VIOLATION] Avoid return Pointer, because memory exists and is destroyed automatically at the end of the function body <===> " + line) except Exception as e: logging.error( "scan_file_SPDBviolation12_2_5 : Error: %s, at line (not allowed on this object) %s", str(e), e.message()) nbNAViolation = nbNAViolation + 1 except Exception as e: logging.error( "scan_file_SPDBviolation12_2_5 : Error: %s, at line ", str(e), current_line) except FileNotFoundError: logging.error("scan_file_SPDBviolation12_2_5 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("scan_file_SPDBviolation12_2_5 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info( "scan_file_SPDBviolation12_2_5 : END %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation12_2_5", nbViolation, nbNAViolation update_counts(tc) # Extra log t = "SPDBviolation12_2_5", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation10_3_3(application, pfile, fileType): # Description: scan_file_SPDBviolation10_3_3 # NOTE # As the rule is widely general and largely semantic, it is tailored only on specific patterns. # It simply finds all function calls which are not assigned to vars. # nbViolation = 0 nbNAViolation = 0 dtType = "float" msecs = local_library.millis() nBytes = 0 logging.debug("pfile.name----" + str(pfile.name)) logging.info( "scan_file_SPDBviolation10_3_3 : -------------------------------------------------------------------------" ) logging.info( "scan_file_SPDBviolation10_3_3 : Starting scan_file_scan_file_SPDBviolation10_3_3 > " + str(pfile.name)) patFunCall = "(float)[ \t\r\n]+([A-Za-z0-9_\-\(\),=\. \t\r\n]+);" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[^,\s][^\,]*[^,\s]*)\s*[;,*=)]" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[a-z]*[A-Z]*[0-9]*)\s*\s*[;,=)]" # patFunCall = "\b(?:(?:auto\s*|const\s*|unsigned\s*|signed\s*|register\s*|volatile\s*|static\s*|void\s*|short\s*|long\s*|char\s*|int\s*|float\s*|double\s*|_Bool\s*|complex\s*)+)(?:\s+\*?\*?\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*[\[;,=)]" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 boolVarsInFile = list() boolExist = 0 for line in f: # Line of code # logging.error("Current line %s", line) current_line += 1 try: resultCom = re.finditer(patComment, line) # logging.debug("resultCom value---" + str(line)) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get function call patterns result = re.finditer(patFunCall, line) # logging.info("Result is: >%s<", result) if (not result is None): for p in result: # logging.debug("result value---" + str(p)) logging.info( "scan_file_scan_file_SPDBviolation10_3_3::Result is: [%s] [%s] [%s]", pfile, line, p.group(2)) checkMultipleVars = p.group(2).split(",") for getVar in checkMultipleVars: logging.debug( "scan_file_SPDBviolation10_3_3 :: getVar value---" + str(getVar)) # logging.info("\n@@@@ "+getVar) if getVar.__contains__('='): varNames = getVar.split("=") if (not varNames is None): varName = varNames[0] logging.info( "scan_file_SPDBviolation10_3_3 :: [PASSED] Value is initialized for " + varName) boolExist = 1 scan_Utilities.unConditionalCheck( line, pfile, current_line, p, f, varName, dtType) else: logging.debug( "scan_file_SPDBviolation10_3_3 :: Violation saved for getVar value---" + str(getVar)) boolExist = 1 scan_Utilities.unConditionalCheck( line, pfile, current_line, p, f, getVar, dtType) bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) except Exception as e: logging.error( "scan_file_SPDBviolation10_3_3 : Error: %s, at line ", str(e), current_line) if boolExist: for line1 in f: logging.info(line1) except FileNotFoundError: logging.error("scan_file_SPDBviolation10_3_3 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("scan_file_SPDBviolation10_3_3 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info( "scan_file_SPDBviolation10_3_3 : END %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation10_3_3", nbViolation, nbNAViolation update_counts(tc) # Extra log t = "SPDBviolation10_3_3", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_OMG_RLB_18(application, pfile, fileType): # Author : MGE # last modification date: 24/3/2017 # Description: OMG-ASCCRM-RLB-18: Storable and Member Data Element Initialization with Hard-Coded Network Resource Configuration Data # Languages : C/C++/C# # Property : CWEforFDA_CustomMetrics_C_CPP.OMGRLB18violationCPP - CatID=2002000 PropID=2002024 SubID=2002274 QRID=2002598 # CWEforFDA_CustomMetrics_CSharp.OMGRLB18violationCSharp - CatID=2003000 PropID=2003024 SubID=2003274 QRID=2003598 # NOTE # # # nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("OMG-RLB-18 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("OMG-RLB-18 : Starting scan_file_OMG_RLB_18 > " + str(pfile.name)) patNetResource1 = "([12]?[0-5]?[0-9]\.[12]?[0-5]?[0-9]\.[12]?[0-5]?[0-9]\.[12]?[0-5]?[0-9])" patNetResource2 = "(http[s]?://)|(ftp://)|(mailto://)|(file://)|(data://)|(irc://)" patNetResource3 = "(www\.)|(ftp\.)" patNetResource4 = "([\?\&][ \t]*[a-z0-9\-\_]+[ \t]*\=[ \t]*[a-z0-9\-\_]+)" # All pattern included in double quotes (strings) patNetResource = "[^=]=[ \t]*\".*("+patNetResource1+"|"+patNetResource2+"|"+patNetResource3+"|"+patNetResource4+").*\"" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 # Comment Exclusion - Start resultCom = re.finditer(patComment, line) if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get the most specific object containing the line obj = pfile.find_most_specific_object(current_line, 1) result = re.finditer(patNetResource, line) isFirstViolation = True if not result is None: for p in result: # Set a bookmark for violation bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) #logging.debug("scan_file_OMG_RLB_18 : Found violation > %s at line %s, col. %s", p.group(), current_line, p.start()+1) if fileType == "CCPP": #logging.debug("saving violation for CCPP > %s at line %s, col. %s", p.group(), current_line, p.start()+1) if isFirstViolation: try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.OMGRLB18violationCPP',bk) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-18: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 isFirstViolation = False #local_library.cwefdaLoggerInfo("SAVED CCPP") if fileType == "CSHARP": #logging.debug("saving violation forCSHARP > %s at line %s, col. %s", p.group(), current_line, p.start()+1) if isFirstViolation: try: obj.save_violation('CWEforFDA_CustomMetrics_CSharp.OMGRLB18violationCSharp',bk) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-18: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 isFirstViolation = False #local_library.cwefdaLoggerInfo("CSHARP") except FileNotFoundError: logging.error("OMG-RLB-18 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("OMG-RLB-18 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("OMG-RLB-18 : END scan_file_OMG_RLB_18 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "OMG-RLB-18",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "OMG-RLB-18",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_OMG_RLB_9_Step1(application, pfile, fileType): # Author : MGE # last modification date: 24/3/2017 # Description: OMG RLB-9: OMG RLB-9: Float Type Storable and Member Data Element Comparison with Equality Operator # Languages : C/C++/C# # Property : CWEforFDA_CustomMetrics_C_CPP.OMGRLB9violationCPP - CatID=2002000 PropID=2002022 SubID=2002272 QRID=2002594 # CWEforFDA_CustomMetrics_CSharp.OMGRLB9violationCSharp - CatID=2003000 PropID=2003022 SubID=2003272 QRID=2003594 # NOTE # scan_file_OMG_RLB_9_Step1: find all float objects definition and store it # scan_file_OMG_RLB_9_Step2: find all = comparison with float objects involved # The scope is internal to file+function or Global. Lower scopes are not considerered # global aFunctionDefinitionName global aFunctionDefinitionNPar global aFunctionCallName global aFunctionCallNPar global aFunctionCallBookmark global aFloatVariableName global aFloatClassName myIdx=0 isInMultiLineComment = False isInSingleLineComment = False msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("OMG-RLB-9-Step1 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("OMG-RLB-9-Step1 : Starting scan_file_OMG_RLB_9_Step1 > " + str(pfile.name)) patFloatDefinition = "((float)|(double)|(long double))([ \t\r\n]+)([A-Za-z0-9_\-\(\),=\. \t\r\n]+);" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" #rfCall= ReferenceFinder() #rfCall.add_pattern('patFloatDefinition', before='', element = patFloatDefinition, after='') #rfCall.add_pattern('patComment', before='', element = patComment, after='') try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) resultPatFloatDef = re.finditer(patFloatDefinition, line) if not resultPatFloatDef is None: #if reference.pattern_name=='patFloatDefinition': ps = re.compile('([A-Za-z][A-Za-z0-9_\-]*)([ \t\r\n]*)(\([A-Za-z0-9_\- \t\r\n.,\.\*]*\))') codeWithoutFunctions = ps.sub('|NullF|',line) ps = re.compile('([ \t\r\n]*)=([ \t\r\n]*)([0-9\.]+)') codeWithoutAssign = ps.sub('',codeWithoutFunctions) #logging.debug("----------------------------%s-----------------------",codeWithoutFunctions) result = re.finditer(patFloatDefinition, codeWithoutAssign) for p in result: # Bookmark(File(TestCase.cs, CAST_DotNet_CSharpFile), 28, 19, 28, 33) #local_library.cwefdaLoggerInfo("%s",reference.bookmark) bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) current_line = int(str(bk).split(",")[2]) #current_line = int(str(reference.bookmark).split(",")[2]) #local_library.cwefdaLoggerInfo("%s %s",str(current_line), nScp) tScp = pfile.find_most_specific_object(current_line, 1).get_name() tVar = p.group(6) #logging.debug("=================== Global: %s %s", tScp, tVar) if (tScp == tVar): nVar = "[Global]." + tVar else: nVar = "[" + pfile.get_path()+"]." + tScp + "." + tVar #logging.debug("=================== Var: %s ", nVar) variableIsPresent = False # Check deleted for performance reason, a little amout of duplication is better if not variableIsPresent: aFloatVariableName.append(1) myIdx = len(aFloatVariableName)-1 aFloatVariableName[myIdx] = nVar #logging.debug("----------------------------OMG_RLB_9_Step1: adding aFloatVariableName > %s ", self.aFloatVariableName[myIdx]) except FileNotFoundError: logging.error("OMG-RLB-9-Step1 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("OMG-RLB-9-Step1 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("OMG-RLB-9-Step1 : END OMG-RLB-9-Step1 %s - Found %s definitions ", str(myIdx)) #Extra log t = "OMG-RLB-9-STEP1",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation9_1_3(application, pfile, fileType): # Description: CWE-252 : Unchecked Return Value # Languages : C/C++/C# # Property : CWEforFDA_CustomMetrics_C_CPP.CWE252violationCPP - CatID=2002000 PropID=2002004 SubID=2002254 QRID=2002558 # CWEforFDA_CustomMetrics_CSharp.CWE252violationCPP - CatID=2003000 PropID=2003004 SubID=2003254 QRID=2003558 # Scope & Property : Scope by fn 100010 (n. of function calls) # NOTE # As the rule is widely general and largely semantic, it is tailored only on specific patterns. # It simply finds all function calls which are not assigned to vars. # nbViolation = 0 nbNAViolation = 0 msecs = local_library.millis() nBytes = 0 logging.debug("pfile.name----" + str(pfile.name)) logging.info( "SPDBviolation9_1_3 : -------------------------------------------------------------------------" ) logging.info( "SPDBviolation9_1_3 : Starting scan_file_SPDBviolation9_1_3 > " + str(pfile.name)) patFunCall = "(float|int|char|bool)[ \t\r\n]+([A-Za-z0-9_\-\(\),=\. \t\r\n]+);" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 for line in f: # Line of code # logging.error("Current line %s", line) current_line += 1 try: resultCom = re.finditer(patComment, line) # logging.debug("resultCom value---" + str(line)) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get function call patterns result = re.finditer(patFunCall, line) # logging.info("Result is: >%s<", result) if (not result is None): for p in result: logging.debug( "scan_file_SPDBviolation9_1_3 :: result value---" + str(p)) # logging.info("scan_file_SPDBviolation9_1_3::Result is: [%s] [%s] [%s] [%s] ", pfile, line, p.group(2), p.group(7)) checkMultipleVars = p.group(2).split(",") for getVar in checkMultipleVars: logging.debug( "scan_file_SPDBviolation9_1_3 :: getVar value---" + str(getVar)) # logging.info("\n@@@@ "+getVar) if getVar.__contains__('='): logging.info( "SPDBviolation9_1_3 :: [PASSED] Value is initialized for " + getVar) else: logging.debug( "Violation saved for getVar value---" + str(getVar)) bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation9_1_3', bk) # Set a bookmark for violation # obj = pfile # obj = pfile.find_most_specific_object(current_line, 1) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) # try: # logging.error("SPDBviolation9_1_3 :: [VIOLATION] Value is NOT initialized for " + getVar) # obj.save_violation('SPDB_CustomMetrics_C.SPDBviolation9_1_3', bk) # except Exception as e: # logging.error("SPDBviolation9_1_3: Violation not allowed on this object, next version %s", str(e.message())) # nbNAViolation = nbNAViolation + 1 # else: # nbViolation += 1 # except Exception as e: logging.error("SPDBviolation9_1_3 : Error: %s, at line ", str(e), current_line) except FileNotFoundError: logging.error("SPDBviolation9_1_3 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("SPDBviolation9_1_3 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info( "SPDBviolation9_1_3 : END scan_file_CWE_252 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation9_1_3", nbViolation, nbNAViolation # update_counts(tc) # Extra log t = "SPDBviolation9_1_3", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_OMG_MNT_3(application, pfile, fileType): # Author : PMB # last modification date: 10/4/2017 # Description: OMG MNT-3: OMG MNT-3: Storable and Member Data Element Initialization with Hard-Coded Literals, Float Type Storable and Member Data Element Comparison with Equality Operator # Languages : C/C++/C# # Property : CWEforFDA_CustomMetrics_C_CPP.OMGRLB9violationCPP - CatID=2002000 PropID=2002021 SubID=2002271 QRID=2002592 # CWEforFDA_CustomMetrics_CSharp.OMGRLB9violationCSharp - CatID=2003000 PropID=2003021 SubID=2003271 QRID=2003592 # NOTE # nbViolation=0 nbNAViolation = 0 nbProgramCall=0 isInMultiLineComment = False isInSingleLineComment = False #SCS msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("OMG-MNT-3 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("OMG-MNT-3 : Starting scan_file_OMG_MNT_3 > " + str(pfile.name)) patFloatDefinition = "((const)|(char)|(float)|(double)|(long double))([ \t\r\n]+)([A-Za-z0-9_\-\(\),=\. \t\r\n]+);" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End #SCS nBytes = nBytes + len(line) obj = pfile.find_most_specific_object(current_line, 1) #logging.debug("Statement to analyze >> %s", current_line) resultFloat = re.finditer(patFloatDefinition, line) if not resultFloat is None: for p in resultFloat: if p.group(1) != "const": #newPat=re.compile('([ \t\r\n]+)([A-Za-z0-9_\-\(\)\. \t\r\n]+)([\= ]+)([\d]+)([ \;]+)') #bpm if p.group(1) == "char": newPat=re.compile('([ \t\r\n]+)([A-Za-z0-9_\-\(\)\. \t\r\n]+)([\= ]+)([.\d]+)([ \;]+)') resultNewPat = re.finditer(newPat, line) else: newPat=re.compile('([ \t\r\n]+)([A-Za-z0-9_\-\(\)\. \t\r\n]+)([\= ]+)([\d]+)([ \;]+)') resultNewPat = re.finditer(newPat, line) for pp in resultNewPat: if fileType =="CCPP": bk = Bookmark(pfile,current_line,pp.start()+1,current_line,pp.end()) try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.OMGMNT3violationCPP',bk) except: local_library.cwefdaLoggerWarning("OMG-MNT-3 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 nbProgramCall += 1 if fileType =="CSHARP": bk = Bookmark(pfile,current_line,pp.start()+1,current_line,pp.end()) try: obj.save_violation('CWEforFDA_CustomMetrics_CSharp.OMGMNT3violationCSharp',bk) except: local_library.cwefdaLoggerWarning("OMG-MNT-3 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 nbProgramCall += 1 except FileNotFoundError: logging.error("OMG-MNT-3 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("OMG-MNT-3 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("OMG-MNT-3 : END scan_file_OMG_MNT_3 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "OMG-MNT-3",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "OMG-MNT-3",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def read_xml_file(path, log=None): """ Read an xml file and return the root node as for lxml.etree """ def remove_utf8_from_xml(fileContent): """ Removes the header from the file content. <?xml version="1.0" encoding="UTF-8"?> """ indexStart = fileContent.find('<?xml') if indexStart < 0: return fileContent indexStart = fileContent.find('<', indexStart + 2) if indexStart < 0: return fileContent return fileContent[indexStart:] def remove_xmlns_from_xml(fileContent): """ Removes the "xmlns=" part from file content because lxml api supports this part only by specifying exactly its value whenever we want to access a part of xml content, and its value can change between xml files. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> </web-app> """ if not 'xmlns=' in fileContent: return fileContent indexStart = fileContent.find('xmlns=') indexValueStart = fileContent.find('"', indexStart) if indexValueStart < 0: return fileContent indexValueEnd = fileContent.find('"', indexValueStart + 1) if indexValueEnd < 0: return fileContent return fileContent.replace(fileContent[indexStart:indexValueEnd + 1], '') ''' def get_root(text): class LineNumberingParser(ET.XMLParser): def _start(self, *args, **kwargs): # Here we assume the default XML parser which is expat # and copy its element position attributes into output Elements element = super(self.__class__, self)._start(*args, **kwargs) element.start_line_number = self.parser.CurrentLineNumber element.start_column_number = self.parser.CurrentColumnNumber element._start_byte_index = self.parser.CurrentByteIndex return element def _end(self, *args, **kwargs): element = super(self.__class__, self)._end(*args, **kwargs) element.end_line_number = self.parser.CurrentLineNumber element.end_column_number = self.parser.CurrentColumnNumber element._end_byte_index = self.parser.CurrentByteIndex return element return ET.fromstring(text, LineNumberingParser()) ''' with open_source_file(path) as f: file_content = f.read() file_content = remove_utf8_from_xml(file_content) file_content = remove_xmlns_from_xml(file_content) parser = ET.XMLParser(recover=True) return ET.fromstring(file_content, parser)
def scan_file_CWE_910(application, pfile, fileType): # Author : PMB # last modification date: 27/3/2017 # Description: CWE_910: Use of Expired File Descriptor # Languages : C/C++ # Property : CWEforFDA_CustomMetrics_C_CPP.CWE910violationCPP - CatID=2002000 PropID=2002020 SubID=2002270 QRID=2002590 # NOTE: The software uses or accesses a file descriptor after it has been closed. After a file descriptor for a particular # file or device has been released, it can be reused. The code might not write to the original file, since the reused # file descriptor might reference a different file or device.The code uses an operator for comparison when the intention # was to perform an assignment. # In many languages, the compare statement is very close in appearance to the assignment statement; they are often confused. # nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False pathMsg= "Niente" allFree = set() flagFree = False #SCS msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-910 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-910 : Starting scan_file_CWE_910 > " + str(pfile.name)) # search string "free" pathSrc="(^[ \t]+)(free)([(\ \(]+)([a-zA-Z0-9_]+)([(\ \)\;]+)" # All pattern included in double quotes (strings) patResource = "(^(.)*)("+pathMsg+")(.*$)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End #SCS nBytes = nBytes + len(line) # Get the most specific object containing the line obj = pfile.find_most_specific_object(current_line, 1) # Search variable if found free before if flagFree: for f in allFree: pathMsg = f #pathMsg = "messageBody" #patResource = "(^(.)*)("+pathMsg+")(.*$)" patResource = "([\t\s\*]*)("+pathMsg+")([\s\t\)\,\;\-\+\*])" #result = re.finditer("(^(.)*)("+pathMsg+")(.*$)", line) result = re.finditer(patResource, line) if not result is None: for p in result: #logging.debug("Found Stmt > %s at line %s, col. %s", p.group(), current_line, p.start()+1) # Set a bookmark for violation and save violation bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) #logging.debug("CWE_910: saving violation for CCPP > %s at line %s, col. %s", p.group(), current_line, p.start()+1) try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE910violationCPP',bk) except: local_library.cwefdaLoggerWarning("CWE-910 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 # Search free stmt result = re.finditer(pathSrc, line) if not result is None: for p in result: #logging.debug("Found Stmt Free > %s at line %s, col. %s", p.group(), current_line, p.start()+1) allFree.add(p.group(4)) flagFree = True except FileNotFoundError: logging.error("CWE-910 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-910 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE-910 : END scan_file_CWE_910 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "CWE-910",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "CWE-910",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_CWE_120_122(application, pfile, fileType): # Author : PMB # last modification date: 28/3/2017 # Description: CWE_120_122: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') # Languages : C/C++ # Property : CWEforFDA_CustomMetrics_C_CPP.CWE120violationCPP - CatID=2002000 PropID=2002001 SubID=2002251 QRID=2002552 # CWEforFDA_CustomMetrics_C_CPP.CWE122violationCPP - CatID=2002000 PropID=2002002 SubID=2002252 QRID=2002554 # CWEforFDA_CustomMetrics_CSharp.CWE120violationCSharp - CatID=2003000 PropID=2003001 SubID=2003251 QRID=2003552 # CWEforFDA_CustomMetrics_CSharp.CWE122violationCSharp - CatID=2003000 PropID=2003002 SubID=2003252 QRID=2003554 # NOTE: The program copies an input buffer to an output buffer without verifying that the size of the input buffer # is less than the size of the output buffer, leading to a buffer overflow. # nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False #SCS msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-120-122 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-120-122 : Starting scan_file_CWE_120_122 > " + str(pfile.name)) # search memcpy and strcpy pathMem = "(^[ \t]+memcpy[ \([a-zA-Z0-9_\s\[\]\-\(\)]+)([ \,]+)([a-zA-Z0-9_]*)([ a-zA-Z0-9\[\]\)\;]+)" pathStr = "(^[ \t]+strcpy[ \([a-zA-Z0-9_\s\[\]\-\(\)]+)([ \,]+)([a-zA-Z0-9_]*)([ a-zA-Z0-9\[\]\)\;]+)" pathIf = "(if[ ]*)([\(]+)([a-zA-Z0-9_]+)([\s\=\>\<\!\s]+)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 VarIf = None for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End #SCS nBytes = nBytes + len(line) # Get the most specific object containing the line obj = pfile.find_most_specific_object(current_line, 1) # check variable on if result = re.finditer(pathIf, line) if not result is None: for p in result: #logging.debug("Found If Stmt > %s at line %s, col. %s", p.group(), current_line, p.start()+1) VarIf = p.group(3) # check memcpy variable result = re.finditer(pathMem, line) if not result is None: for p in result: #logging.debug("Found memcpy Stmt > %s at line %s, col. %s", p.group(), current_line, p.start()+1) VarMem = p.group(3) if VarMem != VarIf: #logging.debug("CWE_120_122: saving violation > %s at line %s, col. %s", p.group(), current_line, p.start()+1) bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) if fileType == "CCPP": try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE120violationCPP',bk) obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE122violationCPP',bk) except: local_library.cwefdaLoggerWarning("CWE-120-122 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 # check strcpy variable result = re.finditer(pathStr, line) if not result is None: for p in result: #logging.debug("Found strcpy Stmt > %s at line %s, col. %s", p.group(), current_line, p.start()+1) VarStr = p.group(3) if VarStr != VarIf: #logging.debug("CWE_120_122: saving violation > %s at line %s, col. %s", p.group(), current_line, p.start()+1) bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) if fileType == "CCPP": try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE120violationCPP',bk) obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE122violationCPP',bk) except: local_library.cwefdaLoggerWarning("CWE-120-122 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 if fileType == "CSHARP": try: obj.save_violation('CWEforFDA_CustomMetrics_CSharp.CWE120violationCSharp',bk) obj.save_violation('CWEforFDA_CustomMetrics_CSharp.CWE122violationCSharp',bk) except: local_library.cwefdaLoggerWarning("CWE-120-122 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 except FileNotFoundError: logging.error("CWE-120-122 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-120-122 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE-120-122 : END scan_file_CWE_120_122 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "CWE-120-122",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "CWE-120-122",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_CWE_783(application, pfile, fileType): # Author : PMB # last modification date: 23/3/2017 # Description: CWE_783: Operator Precedence Logic Error # Languages : C/C++ # Property : CWEforFDA_CustomMetrics_C_CPP.CWE783violationCPP - CatID=2002000 PropID=2002019 SubID=2002269 QRID=2002588 # NOTE: The program uses an expression in which operator precedence causes incorrect logic to be used. # nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False #SCS msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-783 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-783 : Starting scan_file_CWE_783 > " + str(pfile.name)) # search "AuthenticateUser" pathSrc="(if[ ]*)([\(]+)([a-zA-Z0-9_\s\=\s]+)(AuthenticateUser)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End #SCS nBytes = nBytes + len(line) # Get the most specific object containing the line obj = pfile.find_most_specific_object(current_line, 1) result = re.finditer(pathSrc, line) if not result is None: for p in result: #logging.debug("Found Stmt > %s at line %s, col. %s", p.group(), current_line, p.start()+1) if p.group(2) == "(": # Set a bookmark for violation and save violation bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) #logging.debug("CWE_783: saving violation for CCPP > %s at line %s, col. %s", p.group(), current_line, p.start()+1) try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE783violationCPP',bk) except: local_library.cwefdaLoggerWarning("CWE-783 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation +=1 except FileNotFoundError: logging.error("CWE-783 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-783 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE-783 : END scan_file_CWE_783 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "CWE-783",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "CWE-783",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_CWE_685_Step2(application, pfile, fileType): # Author : MGE # last modification date: 24/3/2017 # Description: CWE-685: Function Call With Incorrect Number of Arguments # Languages : C # Property : CWEforFDA_CustomMetrics_C_CPP.CWE685violationCPP - CatID=2002000 PropID=2002016 SubID=2002266 QRID=2003582 # # NOTE # scan_file_CWE_685_Step1: find all function definition and store it with number of parameters defined # scan_file_CWE_685_Step2: find all function call by means of function name found in step1, and compare it with parameters stored # global aFunctionDefinitionName global aFunctionDefinitionNPar global aFunctionCallName global aFunctionCallNPar global aFunctionCallBookmark global aFloatVariableName global aFloatClassName myIdx = 0 nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-685-Step2 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-685-Step2 : Starting scan_file_CWE_685_Step2 > " + str(pfile.name)) patFuncName = "[A-Za-z][A-Za-z0-9_\-]*" patFunctionCall = "("+ patFuncName +")"+"([ \t\r\n]*)(\([A-Za-z0-9_\- \t\r\n.,\.\*]*\))" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) obj = pfile.find_most_specific_object(current_line, 1) try: resultFuncCall = re.finditer(patFunctionCall, line) except: resultFuncCall = None #local_library.cwefdaLoggerWarning("CWE-685-Step2: Cannot apply pattern %s to line %s", patFunctionCall, current_line) if not resultFuncCall is None: for p in resultFuncCall: for f in aFunctionDefinitionName: myIdx = aFunctionDefinitionName.index(f) nFun = p.group(1) nPar = len(p.group(3).split(',')) if (nFun == aFunctionDefinitionName[myIdx] and nPar != aFunctionDefinitionNPar[myIdx]): #local_library.cwefdaLoggerInfo("------------------------------------> Found different parameter!!! %s %s <<-->> %s %s", nFun, str(nPar), self.aFunctionDefinitionName[myIdx], str(self.aFunctionDefinitionNPar[myIdx])) #logging.debug("CWE_685_Step2 : C!!!! Found statement %s ==> %s ", str(reference.value), str(reference.bookmark)) try: bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE685violationCPP',bk) #reference.object.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE685violationCPP', reference.bookmark) except Exception as e: local_library.cwefdaLoggerWarning("CWE-685-Step2: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 except FileNotFoundError: logging.error("CWE-685-Step2 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-685-Step2 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE-685-Step2 : END CWE-685 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "CWE-685-STEP2",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "CWE-685-STEP2",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def unConditionalCheck(line, pfile, identified_line, p, file_path, vari, dtType): with open_source_file(pfile.get_path()) as f: # current line number current_line = 1 # boolVarsInFile = list() # boolExist = 0 logging.info("Identified Variable and Line: %s %s", vari, identified_line) try: for line in f: # Line of code # logging.error("Current line %s", line) # logging.info("Current line: %s", current_line) if current_line > identified_line: # logging.info("STARTED READING LINES: %s", line) patNullCheck = "if\s*\((.*)(?=\))" # logging.error("%s", line) nullRes2 = re.findall(patNullCheck, line) # logging.info("unConditionalCheck :: IF condition present") if nullRes2: # for rs in nullRes2: # ress = rs.group(1) # print(ress) open1 = "(" close1 = ")" patBoolInside = open1 + vari + close1 varExist = re.findall(patBoolInside, line) if varExist: if dtType == "bool": boolValidtrs = re.finditer( "(true|false|TRUE|FALSE|0|1)", line) if (not boolValidtrs is None): for p in boolValidtrs: logging.error( "unConditionalCheck :: VIOLATION : SPDBviolation10_3_1 : Boolean variable is directly compared to 'true', 'false', or 1, 0 => %s %s", vari, line) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) bk = Bookmark(pfile, current_line, 1, current_line, -1) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation10_3_1', bk) break if dtType == "int": intValidtrs = re.finditer( "\(\s*([\w]*)\s*(?=[\)])", line) if (not intValidtrs is None): for p in intValidtrs: logging.error( "unConditionalCheck :: VIOLATION : SPDBviolation10_3_2 : The integer variable should use '==' or '!=' directly compared to 0 %s %s", vari, line) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) bk = Bookmark(pfile, current_line, 1, current_line, -1) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation10_3_2', bk) break if dtType == "float": floatValidtrs = re.finditer( "\(\s*([\w*|0-9.0-9]*)\s*(!=|==)\s*([\w*|0-9.0-9]*)\s*(?=[\)])", line) if (not floatValidtrs is None): for p in floatValidtrs: logging.error( "unConditionalCheck :: VIOLATION : SPDBviolation10_3_3 : Can not compare a floating point variable to any number with an '=='or '!=' => %s %s", vari, line) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) bk = Bookmark(pfile, current_line, 1, current_line, -1) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation10_3_3', bk) break if dtType == "pointer": pointerValidtrs = re.finditer( "\((\s*\w*\s*[^==|!=]\s*\w*\s*)(?=\))", line) if (not pointerValidtrs is None): for p in pointerValidtrs: logging.error( "unConditionalCheck :: VIOLATION : SPDBviolation10_3_4 : Pointer variables should use '==' or '! =' compared with NULL => %s %s", vari, line) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) bk = Bookmark(pfile, current_line, 1, current_line, -1) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation10_3_4', bk) break current_line += 1 except FileNotFoundError: logging.error("unConditionalCheck : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("unConditionalCheck : Error: %s", str(e))
def scan_file_CWE_483(application, pfile, fileType): # Author : MGE # last modification date: 24/3/2017 # Description: CWE-483: Incorrect Block Delimitation # Languages : C/C++/C# # Property : CWEforFDA_CustomMetrics_C_CPP.CWE483violationCPP - CatID=2002000 PropID=2002013 SubID=2002263 QRID=2002598 # CWEforFDA_CustomMetrics_CSharp.CWE483violationCSharp - CatID=2003000 PropID=2003013 SubID=2003263 QRID=2003576 # NOTE # nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-483 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-483 : Starting scan_file_CWE_483 > " + str(pfile.name)) patIfNoBlk1 = "(if[ \t\n\r]*\(([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+)(?!{)([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+);)" patIfNoBlk2 = "(else[ \t\n\r]*([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+)(?!{)([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+);)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" patIfNoBlk = patIfNoBlk1 +"|" + patIfNoBlk2 #rfCall= ReferenceFinder() #rfCall.add_pattern('patIfNoBlk', before='', element = patIfNoBlk, after='') #rfCall.add_pattern('patComment', before='', element = patComment, after='') try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) obj = pfile.find_most_specific_object(current_line, 1) #logging.debug("Statement to analize >> %s", current_line) resultIfNoBlk = re.finditer(patIfNoBlk, line) if not resultIfNoBlk is None: for p in resultIfNoBlk: if fileType == "CCPP": #logging.debug("CWE_483 : C/C++! Found Test statement %s ==> %s", str(reference.value), str(reference.bookmark)) try: bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE483violationCPP',bk) #reference.object.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE483violationCPP', reference.bookmark) except Exception as e: local_library.cwefdaLoggerWarning("CWE-483: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 if fileType == "CSHARP": #logging.debug("CWE_483 : CSHARP! Found Test statement %s ==> %s", str(reference.value), str(reference.bookmark)) try: bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) obj.save_violation('CWEforFDA_CustomMetrics_CSharp.CWE483violationCSharp',bk) #reference.object.save_violation('CWEforFDA_CustomMetrics_CSharp.CWE483violationCSharp', reference.bookmark) except Exception as e: local_library.cwefdaLoggerWarning("CWE-483: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 except FileNotFoundError: logging.error("CWE-483 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-483 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE_483 : END CWE-483 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "CWE-483",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "CWE-483",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def end_application(self, application): logging.info("Filtering violations") # All Cobol properties corresponding to bookmarked quality rules properties = get_properties(application) # 1. register each property as handled by this plugin : we wil rewrite them for prop in properties: application.declare_property_ownership(prop, 'CAST_COBOL_SavedProgram') number_of_programs = 0 number_of_telon_programs = 0 number_of_violations = 0 number_of_kept_violations = 0 telon_LOC = 0 total_LOC = 0 for program in application.objects().has_type( 'CAST_COBOL_SavedProgram').load_violations(properties): # 1. get the violations for that program # a Cobol violation can be in a copybook, we group violations per file violations_per_file = {} number_of_programs += 1 is_telon = False for prop in properties: for violation in program.get_violations(prop): _file = violation[1].file if _file not in violations_per_file: violations_per_file[_file] = [] violations_per_file[_file].append(violation) # 2. filter the violations that are in user code user_code_violations = [] for _file, violations in violations_per_file.items(): # open the file, get the 'user code bookmarks' # those are the 'bookmarks' that represent the user code bookmarks = [] with open_source_file(_file.get_path()) as f: begin_line = 0 current_line = 0 number_of_telon_LOC_in_current_program = 0 for line in f: current_line += 1 if is_begin(line): # store current portion begin begin_line = current_line elif is_end(line): # add a user code bookmark end_line = current_line bookmark = Bookmark(_file, begin_line, 1, current_line, -1) bookmarks.append(bookmark) is_telon = True number_of_telon_LOC_in_current_program += ( end_line - begin_line + 1) # filter the violations that reside in at least one 'user code bookmark' for violation in violations: number_of_violations += 1 for bookmark in bookmarks: # use of contains operator if bookmark.contains(violation[1]): user_code_violations.append(violation) break if not bookmarks: # case where we do not have any marker : keep all violations : maybe we are not in TELON environment user_code_violations.append(violation) if is_telon: number_of_telon_programs += 1 logging.info( 'Number of TELON LOC in current program [%s]: %s on a total of %s LOC' % (_file.get_path(), number_of_telon_LOC_in_current_program, current_line)) total_LOC += current_line telon_LOC += number_of_telon_LOC_in_current_program else: logging.info('File [%s] does not contain any Telon code' % (_file.get_path())) # 3. save back user_code_violations for violation in user_code_violations: number_of_kept_violations += 1 # violation 'format' is almost directly usable as parameter program.save_violation(violation[0], violation[1], violation[2]) # et hop ! logging.info('Found %s TELON programs out of %s programs' % (number_of_telon_programs, number_of_programs)) logging.info('Kept %s violation bookmarks out of %s' % (number_of_kept_violations, number_of_violations)) logging.info( 'Number of TELON LOC : %s on a total of %s LOC, which means %s percent of generated LOC' % (telon_LOC, total_LOC, round(telon_LOC * 100 / total_LOC, 2))) logging.info("Done filtering violations")
def scan_file_OMG_RLB_9_Step2(application, pfile, fileType): # Author : MGE # last modification date: 24/3/2017 # Description: OMG RLB-9: OMG RLB-9: Float Type Storable and Member Data Element Comparison with Equality Operator # Languages : C/C++/C# # Property : CWEforFDA_CustomMetrics_C_CPP.OMGRLB9violationCPP - CatID=2002000 PropID=2002022 SubID=2002272 QRID=2002594 # CWEforFDA_CustomMetrics_CSharp.OMGRLB9violationCSharp - CatID=2003000 PropID=2003022 SubID=2003272 QRID=2003594 # NOTE # scan_file_OMG_RLB_9_Step1: find all float objects definition and store it # scan_file_OMG_RLB_9_Step2: find all = comparison with float objects involved # The scope is internal to file+function or Global. Lower scopes are not considerered # global aFunctionDefinitionName global aFunctionDefinitionNPar global aFunctionCallName global aFunctionCallNPar global aFunctionCallBookmark global aFloatVariableName global aFloatClassName myIdx = 0 nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("OMG-RLB-9-Step2 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("OMG-RLB-9-Step2 : Starting scan_file_OMG_RLB_9_Step2 > " + str(pfile.name)) patFloatName = "[A-Za-z0-9_\-\.]*" patFloatCompLeft = "("+ patFloatName +")" + "([A-Za-z0-9_ \(\)\t\r\n\*\+\-\/]*[\=][\=])" patFloatCompRight = "(==[A-Za-z0-9_ \(\)\t\r\n\*\+\-\/]*)" + "("+ patFloatName +")" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) obj = pfile.find_most_specific_object(current_line, 1) #logging.debug("Statement to analize >> %s", current_line) try: resultpatFloatRigh = re.finditer(patFloatCompRight, line) except: resultpatFloatRigh = None #local_library.cwefdaLoggerWarning("OMG-RLB-9-Step2: Cannot apply pattern %s to line %s", patFloatCompRight, current_line) # --- Scan for pattern on the right # ------------------------------------------------------------------------------------ if not resultpatFloatRigh is None: for p in resultpatFloatRigh: for myIdx in range(len(aFloatVariableName)): bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) current_line = int(str(bk).split(",")[2]) tVar = p.group(2) tScp = pfile.find_most_specific_object(current_line, 1).get_name() if (tScp == tVar): nVar = "[Global]." + tVar else: nVar = "[" + pfile.get_path()+"]." + tScp + "." + tVar if (nVar == aFloatVariableName[myIdx]): if fileType == "CCPP": #logging.debug("RLB-9: C/C++! Found Test statement %s ==> %s", str(reference.value), str(reference.bookmark)) try: #bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.OMGRLB9violationCPP',bk) #reference.object.save_violation('CWEforFDA_CustomMetrics_C_CPP.OMGRLB9violationCPP', reference.bookmark) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-9-Step2: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 if fileType == "CSHARP": #logging.debug("RLB-9 : CSHARP! Found Test statement %s ==> %s", str(reference.value), str(reference.bookmark)) try: #bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) obj.save_violation('CWEforFDA_CustomMetrics_CSharp.OMGRLB9violationCSharp',bk) #reference.object.save_violation('CWEforFDA_CustomMetrics_CSharp.OMGRLB9violationCSharp', reference.bookmark) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-9-Step2: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 try: resultpatFloatLeft = re.finditer(patFloatCompLeft, line) except: resultpatFloatLeft = None #local_library.cwefdaLoggerWarning("OMG-RLB-9-Step2: Cannot apply pattern %s to line %s", patFloatCompLeft, current_line) # --- Scan for pattern on the left # ------------------------------------------------------------------------------------ if not resultpatFloatLeft is None: for p in resultpatFloatLeft: for myIdx in range(len(aFloatVariableName)): bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) current_line = int(str(bk).split(",")[2]) tVar = p.group(1) tScp = pfile.find_most_specific_object(current_line, 1).get_name() if (tScp == tVar): nVar = "[Global]." + tVar else: nVar = "[" + pfile.get_path()+"]." + tScp + "." + tVar if (nVar == aFloatVariableName[myIdx]): if fileType == "CCPP": #logging.debug("RLB-9: C/C++! Found Test statement %s ==> %s", str(reference.value), str(reference.bookmark)) try: #bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.OMGRLB9violationCPP',bk) #reference.object.save_violation('CWEforFDA_CustomMetrics_C_CPP.OMGRLB9violationCPP', reference.bookmark) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-9-Step2: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 if fileType == "CSHARP": #logging.debug("RLB-9 : CSHARP! Found Test statement %s ==> %s", str(reference.value), str(reference.bookmark)) try: #bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) obj.save_violation('CWEforFDA_CustomMetrics_CSharp.OMGRLB9violationCSharp',bk) #reference.object.save_violation('CWEforFDA_CustomMetrics_CSharp.OMGRLB9violationCSharp', reference.bookmark) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-9-Step2: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 except FileNotFoundError: logging.error("OMG-RLB-9-Step2 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("OMG-RLB-9-Step2 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("OMG-RLB-9-Step2 : END RLB-9-Step2 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "OMG-RLB-9-STEP2",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "OMG-RLB-9-STEP2",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation9_1_3(application, pfile, fileType): # Description: scan_file_SPDBviolation9_1_3 # NOTE # As the rule is widely general and largely semantic, it is tailored only on specific patterns. # It simply finds all function calls which are not assigned to vars. # nbViolation = 0 nbNAViolation = 0 msecs = local_library.millis() nBytes = 0 logging.debug("pfile.name----" + str(pfile.name)) logging.info( "SPDBviolation9_1_3 : -------------------------------------------------------------------------" ) logging.info( "SPDBviolation9_1_3 : Starting scan_file_SPDBviolation9_1_3 > " + str(pfile.name)) patFunCall = "(float|int|char|bool)[ \t\r\n]+([A-Za-z0-9_\-\(\),=\. \t\r\n]+);" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 for line in f: # Line of code # logging.error("Current line %s", line) current_line += 1 try: resultCom = re.finditer(patComment, line) # logging.debug("resultCom value---" + str(line)) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get function call patterns result = re.finditer(patFunCall, line) # logging.info("Result is: >%s<", result) if (not result is None): for p in result: logging.debug( "scan_file_SPDBviolation9_1_3 :: result value---" + str(p)) # logging.info("scan_file_SPDBviolation9_1_3::Result is: [%s] [%s] [%s] [%s] ", pfile, line, p.group(2), p.group(7)) checkMultipleVars = p.group(2).split(",") for getVar in checkMultipleVars: logging.debug( "scan_file_SPDBviolation9_1_3 :: getVar value---" + str(getVar)) # logging.info("\n@@@@ "+getVar) if getVar.__contains__('='): logging.info( "SPDBviolation9_1_3 :: [PASSED] Value is initialized for " + getVar) else: logging.debug( "Violation saved for getVar value---" + str(getVar)) # Set a bookmark bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation9_1_3', bk) except Exception as e: logging.error("SPDBviolation9_1_3 : Error: %s, at line ", str(e), current_line) except FileNotFoundError: logging.error("SPDBviolation9_1_3 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("SPDBviolation9_1_3 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info("SPDBviolation9_1_3 : END %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation9_1_3", nbViolation, nbNAViolation # update_counts(tc) # Extra log t = "SPDBviolation9_1_3", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_OMG_RLB_12(application, pfile, fileType): # Author : MGE # last modification date: 29/3/2017 # Description: OMG RLB-12: OMG RLB-12: Singleton Class Instance Creation without Proper Lock Element Management # Languages : C++/C# # Property : CWEforFDA_CustomMetrics_C_CPP.OMGRLB12violationCPP - CatID=2002000 PropID=2002023 SubID=2002273 QRID=2002596 # CWEforFDA_CustomMetrics_CSharp.OMGRLB12ViolationCSharp - CatID=2003000 PropID=2003023 SubID=2003273 QRID=2003596 # NOTE # 1) find all classes implementing singleton (with ""new className"" inside) # 2) find all singleton classes without any lock primitive inside the method containing new # nbViolation = 0 nbNAViolation = 0 myIdx = -1 isInMultiLineComment = False isInSingleLineComment = False aClass = [] aClassIsSingleton = [] aBookmark = [] aIsViolation = [] aCastSingletonObj = [] msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("OMG-RLB-12 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("OMG-RLB-12 : Starting scan_file_OMG_RLB_12 > " + str(pfile.name)) patClassDefinition = "(class[ \t]+)([A-Za-z0-9_\-]+)" patLockUsage = "([Ll][Oo][Cc][Kk])" #patBodyStart = "\{" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 #classDefinition = False for line in f: # Line of code current_line += 1 # Comment Exclusion - Start resultCom = re.finditer(patComment, line) if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get the most specific object containing the line #if myIdx != 0: #obj = pfile.find_most_specific_object(current_line, 1) #local_library.cwefdaLoggerInfo("=====================================================") #local_library.cwefdaLoggerInfo("= Line: %s",str(current_line) ) #local_library.cwefdaLoggerInfo("= Cast Object: %s",obj ) #local_library.cwefdaLoggerInfo("= Cast Object Type: %s",obj.get_type()) #local_library.cwefdaLoggerInfo("=====================================================") r1 = re.finditer(patClassDefinition, line) if not r1 is None: for p1 in r1: #bk = Bookmark(pfile,current_line,p1.start()+1,current_line,p1.end()) aClass.append(1) aBookmark.append(1) aIsViolation.append(1) aCastSingletonObj.append(1) aClassIsSingleton.append(1) myIdx = len(aClass)-1 aClass[myIdx] = p1.group(2) aIsViolation[myIdx] = True aClassIsSingleton[myIdx] = False patSingletonDefinition = "(new[ \t]+" + p1.group(2) +")" #local_library.cwefdaLoggerInfo("=====================================================") #local_library.cwefdaLoggerInfo("= myIdx: %d",myIdx) #local_library.cwefdaLoggerInfo("= Class: %s",aClass[myIdx]) #local_library.cwefdaLoggerInfo("= Violation: %s",aIsViolation[myIdx]) #local_library.cwefdaLoggerInfo("= patSingletonDefinition: %s",patSingletonDefinition) #local_library.cwefdaLoggerInfo("=====================================================") if myIdx != -1: r2 = re.finditer(patSingletonDefinition, line) if not r2 is None: for p2 in r2: #local_library.cwefdaLoggerInfo(" in patSingletonDefinition FOUND") aCastSingletonObj[myIdx] = pfile.find_most_specific_object(current_line, p2.start()-3) aBookmark[myIdx] = Bookmark(pfile,current_line,p2.start()+1,current_line,p2.end()) aClassIsSingleton[myIdx] = True #local_library.cwefdaLoggerInfo("Tipo Obj: %s ", type(aCastSingletonObj[myIdx])) #local_library.cwefdaLoggerInfo("Is Singleton??? %d ",current_line) #local_library.cwefdaLoggerInfo("Obj: %s ", aCastSingletonObj[myIdx].get_name()) r3 = re.finditer(patLockUsage, line) if not r3 is None: aIsViolation[myIdx] = False #for p3 in r3: #local_library.cwefdaLoggerInfo(" in patLockUsage FOUND") #curObj = pfile.find_most_specific_object(current_line, 1) #local_library.cwefdaLoggerInfo(" curObj = %s", curObj.get_name()) #aIsViolation[myIdx] = False for vIdx in range(len(aClass)): #local_library.cwefdaLoggerInfo("=====================================================") #local_library.cwefdaLoggerInfo("= Class : %s",aClass[vIdx]) #local_library.cwefdaLoggerInfo("= Is Singleton: %s",aClassIsSingleton[vIdx]) #local_library.cwefdaLoggerInfo("= Bookmark: %s", aBookmark[vIdx]) #local_library.cwefdaLoggerInfo("= Violation: %s",aIsViolation[vIdx]) #local_library.cwefdaLoggerInfo("= Cast Sinlgeton Obj : %s",aCastSingletonObj[vIdx].get_name()) #local_library.cwefdaLoggerInfo("=====================================================") if aClassIsSingleton[vIdx] and aIsViolation[vIdx]: if fileType == "CCPP": try: aCastSingletonObj[vIdx].save_violation('CWEforFDA_CustomMetrics_C_CPP.OMGRLB12violationCPP', aBookmark[vIdx]) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-12: Violation not allowed on this kind of object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 #local_library.cwefdaLoggerInfo("SAVED CCPP") if fileType == "CSHARP": try: aCastSingletonObj[vIdx].save_violation('CWEforFDA_CustomMetrics_CSharp.OMGRLB12violationCSharp',aBookmark[vIdx]) except Exception as e: local_library.cwefdaLoggerWarning("OMG-RLB-12: Violation not allowed on class object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 #local_library.cwefdaLoggerInfo("SAVED CSHARP") except FileNotFoundError: logging.error("OMG-RLB-12 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("OMG-RLB-12 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("OMG-RLB-12 : END scan_file_OMG_RLB_12 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "OMG-RLB-12",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "OMG-RLB-12",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def end_application(self, application): logging.info("Filtering violations") # All Cobol properties corresponding to bookmarked quality rules properties = get_properties(application) # 1. register each property as handled by this plugin : we will rewrite them for prop in properties: application.declare_property_ownership(prop, 'CAST_COBOL_SavedProgram') number_of_programs = 0 number_of_cobol_programs = 0 number_of_cobol_copybooks = 0 number_of_hra_programs = 0 number_of_violations = 0 number_of_kept_violations = 0 hra_LOC = 0 total_LOC = 0 for program in application.objects().has_type( 'CAST_COBOL_SavedProgram').load_violations(properties): # 1. get the violations for that program # a Cobol violation can be in a copybook, we group violations per file violations_per_file = {} number_of_programs += 1 is_hra = False for prop in properties: for violation in program.get_violations(prop): _file = violation[1].file if _file not in violations_per_file: violations_per_file[_file] = [] violations_per_file[_file].append(violation) # 2. filter the violations that are in user code user_code_violations = [] for _file, violations in violations_per_file.items(): if program != _file: #CobolFileType = 'CopyBook' # we are in a Copybook number_of_cobol_copybooks += 1 else: #CobolFileType = 'Program' # we are not in the program not a Copybook number_of_cobol_programs += 1 # open the file, get the 'user code bookmarks' # those are the 'bookmarks' that represent the user code bookmarks = [] with open_source_file(_file.get_path()) as f: #logging.info('current file (%s) =[ %s ] ' % (CobolFileType, _file.get_path())) begin_line = 0 current_line = 0 number_of_hra_LOC_in_current_file = 0 for line in f: current_line += 1 if is_begin(line): # store current portion begin #logging.info('begin_line =[ %s ] ' % (line)) begin_line = current_line elif is_end(line): # add a user code bookmark end_line = current_line bookmark = Bookmark(_file, begin_line, 1, current_line, -1) #logging.info('end_line =[ %s ] ' % (line)) #logging.info('bookmark file =[ %s ], begin_line = %s end_line = %s ' % (_file, begin_line, end_line)) bookmarks.append(bookmark) is_hra = True number_of_hra_LOC_in_current_file += (end_line - begin_line + 1) # filter the violations that reside in at least one 'user code bookmark' for violation in violations: number_of_violations += 1 for bookmark in bookmarks: # use of contains operator if bookmark.contains(violation[1]): user_code_violations.append(violation) break if not bookmarks: # case where we do not have any marker : keep all violations : maybe we are not in HR Access environment user_code_violations.append(violation) if (number_of_hra_LOC_in_current_file != 0): logging.info( 'Number of customer code LOC in current file [%s]: %s on a total of %s LOC' % (_file.get_path(), number_of_hra_LOC_in_current_file, current_line)) total_LOC += current_line hra_LOC += number_of_hra_LOC_in_current_file else: logging.info( 'File [%s] does not contain any customer code, file LOC = %s' % (_file.get_path(), current_line)) total_LOC += current_line if is_hra: number_of_hra_programs += 1 # 3. save back user_code_violations for violation in user_code_violations: number_of_kept_violations += 1 # violation 'format' is almost directly usable as parameter program.save_violation(violation[0], violation[1], violation[2]) # et hop ! if (total_LOC > 0): logging.info( 'Found %s HR Access programs out of %s programs and %s copybooks' % (number_of_hra_programs, number_of_programs, number_of_cobol_copybooks)) logging.info('Kept %s violation bookmarks out of %s' % (number_of_kept_violations, number_of_violations)) logging.info( 'Number of HR Access LOC : %s on a total of %s LOC, which means %s percent of generated LOC' % (hra_LOC, total_LOC, round(hra_LOC * 100 / total_LOC, 2))) logging.info("Done filtering violations") else: logging.info( '*** No Cobol files analyzed, so no HR Access code to filter')
def scan_file_CWE(application, pfile, fileType): # Languages : C # nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False msecs = local_library.millis() nBytes = 0 patIfNoBlk1 = "(if[ \t\n\r]*\(([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+)(?!{)([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+);)" patIfNoBlk2 = "(else[ \t\n\r]*([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+)(?!{)([A-Za-z0-9_\(\)\.\,:\?\=\/\+\-\* \t\n\r]+);)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" patIfNoBlk = patIfNoBlk1 + "|" + patIfNoBlk2 #rfCall= ReferenceFinder() #rfCall.add_pattern('patIfNoBlk', before='', element = patIfNoBlk, after='') #rfCall.add_pattern('patComment', before='', element = patComment, after='') try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) obj = pfile.find_most_specific_object(current_line, 1) #logging.debug("Statement to analize >> %s", current_line) resultIfNoBlk = re.finditer(patIfNoBlk, line) if not resultIfNoBlk is None: for p in resultIfNoBlk: if fileType == "CCPP": #logging.debug("Found Test statement %s ==> %s", str(reference.value), str(reference.bookmark)) try: bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) # obj.save_violation('',bk) except Exception as e: logging.warning( "Violation not allowed on this kind of object, next version" ) nbNAViolation = nbNAViolation + 1 else: nbViolation += 1 except FileNotFoundError: logging.error(" : File not found > " + str(pfile.get_path())) except Exception as e: logging.error(" : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info(" : END %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "", nbViolation, nbNAViolation update_counts(tc) #Extra log t = "", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation10_5_3(application, pfile, fileType): # Description: scan_file_SPDBviolation10_5_3 # NOTE # As the rule is widely general and largely semantic, it is tailored only on specific patterns. # It simply finds all function calls which are not assigned to vars. # nbViolation = 0 nbNAViolation = 0 msecs = local_library.millis() nBytes = 0 logging.debug("pfile.name----" + str(pfile.name)) logging.info( "SPDBviolation10_5_3 : -------------------------------------------------------------------------" ) logging.info( "SPDBviolation10_5_3 : Starting scan_file_SPDBviolation10_5_3 > " + str(pfile.name)) # patswitch = "switch\s*\((.*)(?=)\)" patcase = "(switch|case|default)\s*(.*)(?=)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False switchcheck = 0 matchedcasedefault = 0 matchedswitch = 0 with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 for line in f: # Line of code # logging.error("Current line %s", line) current_line += 1 try: resultCom = re.finditer(patComment, line) # logging.debug("resultCom value---" + str(line)) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # switchcheck=0 # Get function call patterns # isswitch = re.findall(patswitch, line) # if switchcheck == 0: # if isswitch: # logging.info("Current line %s", line) # switchcheck=1 # if switchcheck == 1: if matchedswitch == 1: if matchedcasedefault == 1: nextline = line if nextline.__eq__("\n") or nextline.__contains__( "{"): logging.info( "Empty line - Check in next line %s", nextline) nextline = linecache.getline( pfile.get_path(), current_line + 1) # else: # logging.info("CASE found - Next line %s", nextline ) # logging.debug("Processing next line %s", nextline ) resultCom = re.findall(patComment, nextline) if resultCom: logging.info( "Proper COMMENTES are found in CASE %s", nextline) else: logging.info( "SPDBviolation10_5_3 :: VIOLATION - Each case branch of the switch statement should have comments %s - Line %s", nextline, line) # logging.info("Current line %s type %s", line, p.group(1)) bk = Bookmark(pfile, current_line, 1, current_line, -1) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation10_5_3', bk) matchedcasedefault = 0 isswitchcase = re.finditer(patcase, line) if not isswitchcase is None: for p in isswitchcase: # logging.info("Current line %s", line) if p.group(1) == "switch": logging.info("SWITCH found - Current line %s", line) # logging.info("SWITCH found - Current line %s type %s", line, p.group(1)) matchedswitch = 1 if p.group(1) == "case" or p.group(1) == "default": logging.info("CASE found - Current line %s", line) # logging.info("CASE found - Current line %s type %s", line, p.group(1)) matchedcasedefault = 1 if p.group(1) == "default": logging.info( "DEFAULT found - Current line %s", line) # logging.info("DEFAULT found - Current line %s type %s", line, p.group(1)) matchedcasedefault = 1 except Exception as e: logging.error("SPDBviolation10_5_3 : Error: %s, at line ", str(e), current_line) except FileNotFoundError: logging.error("SPDBviolation10_5_3 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("SPDBviolation10_5_3 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info("SPDBviolation10_5_3 : END %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation10_5_3", nbViolation, nbNAViolation # update_counts(tc) # Extra log t = "SPDBviolation10_5_3", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation14_1_3(application, pfile, fileType): # Description: scan_file_SPDBviolation14_1_3 # NOTE # As the rule is widely general and largely semantic, it is tailored only on specific patterns. # It simply finds all function calls which are not assigned to vars. # nbViolation = 0 nbNAViolation = 0 msecs = local_library.millis() nBytes = 0 logging.info( "scan_file_SPDBviolation14_1_3 : -------------------------------------------------------------------------" ) logging.info( "scan_file_SPDBviolation14_1_3 : Starting scan_file_SPDBviolation14_1_3 > " + str(pfile.name)) patFunCall = "(float|int|char|bool|float\*|int\*|char\*|bool\*)[ \t\r\n]+([a-zA-Z0-9_]*)(\[([^\[\]]+)\]|\[[]])" # patFunCall = "\b(?:(?:int\s*|float\s*|char\s*|bool)+)(?:\s+\*?\*?\s*)([a-zA-Z0-9_]*)\s*(\[.*?\])" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[^,\s][^\,]*[^,\s]*)\s*[;,*=)]" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[a-z]*[A-Z]*[0-9]*)\s*\s*[;,=)]" # patFunCall = "\b(?:(?:auto\s*|const\s*|unsigned\s*|signed\s*|register\s*|volatile\s*|static\s*|void\s*|short\s*|long\s*|char\s*|int\s*|float\s*|double\s*|_Bool\s*|complex\s*)+)(?:\s+\*?\*?\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*[\[;,=)]" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 for line in f: # Line of code # logging.error("Current line %s", line) current_line += 1 try: resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get function call patterns result = re.finditer(patFunCall, line) if (not result is None): for p in result: logging.info( "scan_file_SPDBviolation14_1_3::Result is: %s %s %s ", pfile, line, p.group(1)) # , p.group(7)) getArraySize = 0 if p.group(3) != "[]": getArraySize = p.group(4) logging.info("Value of %s is = %s", p.group(0), getArraySize) else: logging.info("Value of %s is = %s", p.group(0), line) if line.__contains__(','): getArrVales = re.finditer( "{([^}]+)\}|\"([^}]+)\"", line) logging("$$$$$$$$$$$: %s", getArrVales) if (not getArrVales is None): for arrVal in getArrVales: logging("############%s", arrVal) getArraySize = len( arrVal.split(",")) logging("@@@@@@@@@@@@%s", arrVal) logging.info("Value of %s is = %s", p.group(0), getArraySize) else: getArrVales = 0 #------------------------------------------------- else: #--------------- logging.error("NO match for array") except Exception as e: logging.error( "scan_file_SPDBviolation14_1_3 : Error: %s, at line ", str(e), current_line) except FileNotFoundError: logging.error("scan_file_SPDBviolation14_1_3 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("scan_file_SPDBviolation14_1_3 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info( "scan_file_SPDBviolation14_1_3 : END scan_file %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "scan_file_SPDBviolation14_1_3", nbViolation, nbNAViolation update_counts(tc) # Extra log t = "scan_file_SPDBviolation14_1_3", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def find_all_variables(pfile, mode): # Author : SCS # Last modification date : 12/4/2017 # Description: finds all defined variables and return them as a set # Parameters: # pfile File to scan # mode Detection mode: 0 only not initialized, 1 only initialized, 2 all varCount = 0 StdTypes = {"signed long long int", \ "signed short int", "signed long long", "signed long int", \ "signed char", "signed int","signed long", "signed short", \ "signed", \ "unsigned long long int", \ "unsigned short int", "unsigned long int", "unsigned long long", \ "unsigned char", "unsigned long", "unsigned int", "unsigned short", \ "unsigned", \ "long long int", \ "long int", "long double", "long long", \ "long", \ "short int", \ "short", \ "char", "int", "float", "double", "wchar_t", "char16_t", "char32_t" } cwefdaLoggerInfo("CWE4FDA find_all_variables : Scanning file " + str(pfile.name)) allVars = set() # Pattern like int var - group(1) is the var name patSimple = "\s*\**\s*([a-zA-Z0-9_]+)(\s*\[\s*[^\[\]]*\s*\])*\s*;" # Pattern like int var=0 - group(1) is the var name patSimpleInit = "\s*\**\s*([a-zA-Z0-9_]+)(\s*\[\s*[^\[\]]*\s*\])*\s*=[^;]*;" # Pattern like int var1, var2, var3 - group(1) is the list of vars patMultiple = "\s+((\s*\**\s*[a-zA-Z0-9_]+(\s*\[\s*[^\[\]]*\s*\])*\s*\,)+\s*\**\s*[a-zA-Z0-9_]+(\s*\[\s*[^\[\]]*\s*\])*\s*);" # Pattern like var or var[..] - group(1) is the var name patSimpleVar = "([a-zA-Z0-9_]+)(\s*\[\s*[^\[\]]*\s*\])*" # Patterns for function parameters patFunction = "\s*([a-zA-Z0-9_\.]+\s*\**\s*|\(\s*[a-zA-Z0-9_\.]+\s*\**\s*\))\s+([a-zA-Z0-9_\.]+)\s*\(" patMultipleFunPar = "(\s*[a-zA-Z0-9_]+\s*\**\s*[a-zA-Z0-9_]+\s*\,)*\s*[a-zA-Z0-9_]+\s*\**\s*[a-zA-Z0-9_]+\s*\)\s*[\{\;]" patFunPar = "\s*\**\s*([a-zA-Z0-9_]+)(\s*\[\s*[^\[\]]*\s*\])*\s*" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False # .............................................................. # Reads file into a buffer, excluding comments buffer = "" with open_source_file(pfile.get_path()) as f: for line in f: resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End buffer = buffer + line + " " cwefdaLoggerInfo("SPDB find_all_variables : File scanned (size %s) ", len(buffer)) # .............................................................. # Loop on all standard types for variable definitions for p in StdTypes: # Pattern for simple var results = re.finditer(p+patSimple, buffer) if (not results is None): for m in results: var = m.group(1) #logging.info("CWE4FDA find_all_variables : Single Variable with no init %s", str(var)) if (mode == 0 or mode == 2) and (not var in allVars): allVars.add(var) varCount += 1 # Pattern for simple with init results = re.finditer(p+patSimpleInit, buffer) if (not results is None): for m in results: var = m.group(1) #logging.info("CWE4FDA find_all_variables : Single Variable with init %s", str(var)) if (mode == 1 or mode == 2) and (not var in allVars): allVars.add(var) varCount += 1 # Pattern for multiple vars results = re.finditer(p+patMultiple, buffer) if (not results is None): for m in results: mvar = m.group(1) mv = re.finditer(patSimpleVar, mvar) for v in mv: vi = v.group(1) #logging.info("CWE4FDA find_all_variables : Variable in a multiple definition %s (from %s)", str(vi), str(mvar).strip()) if (mode == 0 or mode == 2) and (not vi in allVars): allVars.add(vi) varCount += 1 # .............................................................. # Find function parameters results = re.finditer(patFunction+patMultipleFunPar, buffer) if (not results is None): for mFC in results: mFCode = mFC.group(0) # Get function name m = re.search(patFunction, mFCode) funcName = m.group(2) # Get parameters for p in StdTypes: m = re.finditer(p + patFunPar, mFCode) if (not m is None): for im in m: var = im.group(1) if (var != funcName) and (not var in allVars): #logging.info("CWE4FDA find_all_variables : Variable %s as parameter for function %s", str(var), funcName) allVars.add(var) varCount += 1 except FileNotFoundError: logging.error("SPDB find_all_variables : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("SPDB find_all_variables : Error: %s", str(e)) cwefdaLoggerInfo("SPDB find_all_variables : Found %s variables", str(varCount)) return allVars
def scan_file_SPDBviolation14_1_1(application, pfile, fileType): # Description: SPDBviolation14_1_1: Memory allocation with malloc should be checked with NULL skipFirstPattern = 0 skipSecontPattern = 0 nbViolation = 0 nbNAViolation = 0 isInMultiLineComment = False isInSingleLineComment = False # SCS msecs = local_library.millis() nBytes = 0 logging.info( "14_1_1 : -------------------------------------------------------------------------" ) logging.info("14_1_1 : Starting scan_file_SPDBviolation14_1_1 > " + str(pfile.name)) # search "pthread_mutex_lock" pathSrc = "([a-zA-Z0-9_\.]*)\s*=\s*(\(\s*[a-zA-Z0-9_\.]+\s*\**\s*\))?\s*malloc\s*\(" patNullCheck = "if\s*\((.*)(?=\))" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End # SCS nBytes = nBytes + len(line) if skipFirstPattern == 0: # Get the most specific object containing the line result = re.finditer(pathSrc, line) if not result is None: for p in result: logging.error("MALLOC %s, %s", p.group(1), line) nxtLine = 0 # nextLine = lines[0]+" "+lines[1] # nullRes = re.finditer(patNullCheck, nextLine) module_line = linecache.getline( pfile.get_path(), current_line + 1) logging.error("Attempt to process %s", module_line) if module_line.__eq__("\n"): module_line = linecache.getline( pfile.get_path(), current_line + 2) logging.error("Attempt to process %s", module_line) isValidatedWithIF(module_line, pfile, current_line, p) else: isValidatedWithIF(module_line, pfile, current_line, p) except FileNotFoundError: logging.error("SPDBviolation14_1_1 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("SPDBviolation14_1_1 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.error( "SPDBviolation14_1_1 : END scan_file_SPDBviolation14_1_1 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation14_1_1", nbViolation, nbNAViolation update_counts(tc) # Extra log t = "SPDBviolation14_1_1", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_CWE_685_Step1(application, pfile, fileType): # Author : MGE # last modification date: 24/3/2017 # Description: CWE-685: Function Call With Incorrect Number of Arguments # Languages : C # Property : CWEforFDA_CustomMetrics_C_CPP.CWE685violationCPP - CatID=2002000 PropID=2002016 SubID=2002266 QRID=2003582 # # NOTE # scan_file_CWE_685_Step1: find all function definition and store it with number of parameters defined # scan_file_CWE_685_Step2: find all function call by means of function name found in step1, and compare it with parameters stored # global aFunctionDefinitionName global aFunctionDefinitionNPar global aFunctionCallName global aFunctionCallNPar global aFunctionCallBookmark global aFloatVariableName global aFloatClassName myIdx=0 isInMultiLineComment = False isInSingleLineComment = False msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-685-Step1 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-685-Step1 : Starting scan_file_CWE_685_Step1 > " + str(pfile.name)) #pattern: return_type function_name ( parameter_list ) { body of the function } patFunctionDefinition = "([A-Za-z][A-Za-z0-9_\-]*[ \t]+)([A-Za-z][A-Za-z0-9_\-]*)([ \t\r\n]*)(\([A-Za-z0-9_\- \t\r\n.,\.\*]*\))([ \t\r\n]*){" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" #rfCall= ReferenceFinder() #rfCall.add_pattern('patFunctionDefinition', before='', element = patFunctionDefinition, after='') #rfCall.add_pattern('patComment', before='', element = patComment, after='') try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) resultFuncDef = re.finditer(patFunctionDefinition, line) if not resultFuncDef is None: for p in resultFuncDef: if not (local_library.is_a_keyword(p.group(2)) == 1): nFun = p.group(2) nPar = len(p.group(4).split(',')) functionIsPresent = False for f in aFunctionDefinitionName: if (f == nFun): functionIsPresent = True if not functionIsPresent: aFunctionDefinitionName.append(1) aFunctionDefinitionNPar.append(1) myIdx = len(aFunctionDefinitionName)-1 #local_library.cwefdaLoggerInfo("----------------------------CWE-685: adding FunctionDefinition > %s %s", nFun, nPar) aFunctionDefinitionName[myIdx] = nFun aFunctionDefinitionNPar[myIdx] = nPar except FileNotFoundError: logging.error("CWE-685-Step1 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-685-Step1 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE-685-Step1 : END CWE-685 %s - Found %s definitions ", str(myIdx)) #Extra log t = "CWE-685-STEP1",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)
def scan_file_SPDBviolation9_1_3(application, pfile, fileType): # Description: scan_file_SPDBviolation9_1_3 # NOTE # As the rule is widely general and largely semantic, it is tailored only on specific patterns. # It simply finds all function calls which are not assigned to vars. # nbViolation = 0 nbNAViolation = 0 msecs = local_library.millis() nBytes = 0 logging.debug("pfile.name----" + str(pfile.name)) logging.info( "SPDBviolation9_1_3 : -------------------------------------------------------------------------" ) logging.info( "SPDBviolation9_1_3 : Starting scan_file_SPDBviolation9_1_3 > " + str(pfile.name)) patFunCall = "(float|int|char|bool)[ \t\r\n]+([A-Za-z0-9_\-\(\),=\. \t\r\n]+);" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[^,\s][^\,]*[^,\s]*)\s*[;,*=)]" # patFunCall = "((?:int\s*|float\s*|char\s*|bool\s*)+)(?:\s+\*?\*?\s*)(\s*[a-z]*[A-Z]*[0-9]*)\s*\s*[;,=)]" # patFunCall = "\b(?:(?:auto\s*|const\s*|unsigned\s*|signed\s*|register\s*|volatile\s*|static\s*|void\s*|short\s*|long\s*|char\s*|int\s*|float\s*|double\s*|_Bool\s*|complex\s*)+)(?:\s+\*?\*?\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*[\[;,=)]" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: isInSingleLineComment = False isInMultiLineComment = False with open_source_file(pfile.get_path()) as f: # current line number current_line = 0 for line in f: # Line of code # logging.error("Current line %s", line) current_line += 1 try: resultCom = re.finditer(patComment, line) # logging.debug("resultCom value---" + str(line)) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End nBytes = nBytes + len(line) # Get function call patterns result = re.finditer(patFunCall, line) # logging.info("Result is: >%s<", result) if (not result is None): for p in result: logging.debug("result value---" + str(p)) # logging.info("scan_file_SPDBviolation9_1_3::Result is: [%s] [%s] [%s] [%s] ", pfile, line, p.group(2), p.group(7)) checkMultipleVars = p.group(2).split(",") for getVar in checkMultipleVars: logging.debug("getVar value---" + str(getVar)) # logging.info("\n@@@@ "+getVar) if getVar.__contains__('='): logging.info( "SPDBviolation9_1_3 :: [PASSED] Value is initialized for " + getVar) else: logging.debug( "Violation saved for getVar value---" + str(getVar)) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) bk = Bookmark(pfile, current_line, 1, current_line, -1) pfile.save_violation( 'SPDB_CustomMetrics_C.SPDBviolation9_1_3', bk) # Set a bookmark for violation # obj = pfile # obj = pfile.find_most_specific_object(current_line, 1) # bk = Bookmark(pfile, current_line, p.start() + 1, current_line, p.end()) # try: # logging.error("SPDBviolation9_1_3 :: [VIOLATION] Value is NOT initialized for " + getVar) # obj.save_violation('SPDB_CustomMetrics_C.SPDBviolation9_1_3', bk) # except Exception as e: # logging.error("SPDBviolation9_1_3: Violation not allowed on this object, next version %s", str(e.message())) # nbNAViolation = nbNAViolation + 1 # else: # nbViolation += 1 # except Exception as e: logging.error("SPDBviolation9_1_3 : Error: %s, at line ", str(e), current_line) except FileNotFoundError: logging.error("SPDBviolation9_1_3 : File not found > " + str(pfile.get_path())) except Exception as e: logging.error("SPDBviolation9_1_3 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 logging.info("SPDBviolation9_1_3 : END %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "SPDBviolation9_1_3", nbViolation, nbNAViolation update_counts(tc) # Extra log t = "SPDBviolation9_1_3", int(nBytes / msecs), nBytes, msecs local_library.extraLogWrite(t)
def scan_file_CWE_480_481(application, pfile, fileType): # Author : PMB # Last modification date: 10/4/2017 # Description: CWE-481: Assigning instead of Comparing # Languages: C/C++ C# # Property : CWEforFDA_CustomMetrics_C_CPP.CWE480violationCPP - CatID=2002000 PropID=2002010 SubID=2002260 QRID=2002570 # CWEforFDA_CustomMetrics_C_CPP.CWE481violationCPP - CatID=2002000 PropID=2002011 SubID=2002261 QRID=2002571 # CWEforFDA_CustomMetrics_C_CPP.CWE480violationCSharp - CatID=2003000 PropID=2003010 SubID=2003260 QRID=2003570 # CWEforFDA_CustomMetrics_C_CPP.CWE480violationCSharp - CatID=2003000 PropID=2003011 SubID=2003261 QRID=2003571 # NOTE: The programmer accidentally uses the wrong operator, which changes the application logic in security-relevant ways. # nbProgramCall = 0 isInMultiLineComment = False isInSingleLineComment = False nbViolation=0 nbNAViolation = 0 allIntVars = set() #SCS msecs = local_library.millis() nBytes = 0 local_library.cwefdaLoggerInfo("CWE-480-481 : -------------------------------------------------------------------------") local_library.cwefdaLoggerInfo("CWE-480-481 : Starting scan_file_CWE_480_481 > " +str(pfile.name)) PathIntB = "([\(]+)int ([a-zA-Z0-9_\.]+)" PathIntF = "([ \t]+)int ([a-zA-Z0-9_\.]+)" PathIf = "[ \t]+if([ \(]+)([a-zA-Z0-9_]+)" PathBitWise = "[ \t]+if([ \(]+)([a-zA-Z0-9_\!\(\)]+)( & | \| )+([a-zA-Z0-9_\!\(\)]+)" patComment = "(^[ \t]*[\/][\/])|([\/][\*])|([\*][\/])" try: with open_source_file(pfile.get_path()) as f: #current line number current_line = 0 for line in f: # Line of code current_line += 1 resultCom = re.finditer(patComment, line) # Comment Exclusion - Start if not resultCom is None: for c in resultCom: if c.group(1): isInSingleLineComment = True if c.group(2): isInMultiLineComment = True if c.group(3): isInMultiLineComment = False if isInMultiLineComment: continue if isInSingleLineComment: isInSingleLineComment = False continue # Comment Exclusion - End #SCS nBytes = nBytes + len(line) obj = pfile.find_most_specific_object(current_line, 1) #logging.debug("Statement to analize >> %s >> %s", current_line, line) resultIntB = re.finditer(PathIntB, line) if not resultIntB is None: for c in resultIntB: #logging.debug("CWE_480_481 : Group StmtIntB > %s ", c.group(2)) varIntB=c.group(2) allIntVars.add(varIntB) resultIntF = re.finditer(PathIntF, line) if not resultIntF is None: for c in resultIntF: #logging.debug("CWE_480_481 : Group StmtIntF > %s ", c.group(2)) varIntF=c.group(2) allIntVars.add(varIntF) resultBitWise = re.finditer(PathBitWise, line) if not resultBitWise is None: for c in resultBitWise: if fileType == "CCPP": # Set a bookmark for violation and save violation bk = Bookmark(pfile,current_line,c.start()+1,current_line,c.end()) #logging.debug("sono in test cpp >> %s", bk) try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE480violationCPP',bk) except: local_library.cwefdaLoggerWarning("CWE-480-481 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation +=1 nbProgramCall += 1 continue if fileType == "CSHARP": # Set a bookmark for violation and save violation bk = Bookmark(pfile,current_line,c.start()+1,current_line,c.end()) #logging.debug("sono in test csharp >> %s", bk) try: obj.save_violation('CWEforFDA_CustomMetrics_CSharp.CWE480violationCSharp',bk) except: local_library.cwefdaLoggerWarning("CWE-480-481 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation +=1 nbProgramCall += 1 continue resultPathIf = re.finditer(PathIf, line) if not resultPathIf is None: resultPathIf = re.finditer(PathIf, line) for p in resultPathIf: varIf=p.group(2) for v in allIntVars: if v==varIf: CheckNoEq=line[line.find("!"):line.find("=")+2] CheckLtEq=line[line.find("<"):line.find("=")+2] CheckGtEq=line[line.find(">"):line.find("=")+2] if CheckNoEq or CheckLtEq or CheckGtEq: continue CheckEqEq=line[line.find("="):line.find("=")+2] if not CheckEqEq: continue if CheckEqEq != "==": if fileType == "CCPP": bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) try: obj.save_violation('CWEforFDA_CustomMetrics_C_CPP.CWE481violationCPP',bk) except: local_library.cwefdaLoggerWarning("CWE-480-481 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation +=1 nbProgramCall += 1 if fileType == "CSHARP": bk = Bookmark(pfile,current_line,p.start()+1,current_line,p.end()) try: obj.save_violation('CWEforFDA_CustomMetrics_CSharp.CWE481violationCSharp',bk) except: local_library.cwefdaLoggerWarning("CWE-480-481 : Violation not allowed on this object, next version") nbNAViolation = nbNAViolation + 1 else: nbViolation +=1 nbProgramCall += 1 except FileNotFoundError: logging.error("CWE-480-481 : File not found > " + str(pfile.get_path()) ) except Exception as e: logging.error("CWE-480-481 : Error: %s", str(e)) msecs = local_library.millis() - msecs if msecs == 0: msecs = 1 local_library.cwefdaLoggerInfo("CWE-480-481 : END scan_file_CWE_480_481 %s - Found %s violation ", str(pfile.name), str(nbViolation)) tc = "CWE-480-481",nbViolation,nbNAViolation update_counts(tc) #Extra log t = "CWE-480-481",int(nBytes/msecs),nBytes,msecs local_library.extraLogWrite(t)