コード例 #1
0
 def __init__(self):
     self.vcs = GitProvider(config.getRepoDir())
     self.ccdb = CCDatabase(config.getCcDbFile())
     self.codeChecker = CodeChecker(config.getRepoDir())
     self.checkers = Checkers()
     self.loadCommitList()
コード例 #2
0
 def testDatabaseOpenNonExistingFailure(self):
     dbPath = config.getRepoDir() + "/testtmp.sqlite"
     with self.assertRaises(FileNotFoundError):
         db = CCDatabase(dbPath)
コード例 #3
0
class Predictor():
    def __init__(self):
        self.vcs = GitProvider(config.getRepoDir())
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.checkers = Checkers()
        self.loadCommitList()

    def loadCommitList(self):
        self.commits = self.vcs.getAllVersions(config.getBranch())
        self.currentCommitIndex = 0

    def convertFilePathToRepoRelativePath(self, path):
        return os.path.relpath(path, config.getRepoDir())

    def getDiffResolvedIds(self):
        resolved = self.codeChecker.diffResolved(config.getCcRunName(),
                                                 config.getTmpDir(), self.ccdb)
        ids = []
        for bug in resolved:
            ids.append(bug['reportId'])
        return ids

    def predict(self, id, checker):
        # Load all bugs
        print("Loading bug data...")
        ids = []
        if id == -1:
            bugs = self.ccdb.getAllBugsForChecker(checker)
            ids = [x[0] for x in bugs]
        else:
            ids.append(id)

        # Loading model
        print("Loading model...")
        model = load_model(config.cfModelFilenameFormat.format(checker))
        model.summary()
        vLabels = ['NOT OK', 'OK', 'Skipped']

        # Initialize coder
        print("Initializing coder...")
        self.dictionary = Dictionary(checker)
        self.coder = Coder(self.dictionary)
        self.totalDictionaryLength = self.dictionary.length()

        # Predicting
        print("Starting predictions...")
        for i in ids:
            allData = self.ccdb.getBugData(i)
            if allData.getChecker(
            ) not in globals.availableCheckers or allData.getChecker(
            ) != checker:
                print("Bug #{0} - checker not supported".format(i))
            else:
                # Load extra tokens from checker message
                checkerInfo = self.checkers.extractTokensForChecker(
                    allData.getChecker(), allData.getMessage())
                # Retrieve code fragment with bug
                fileRelativePath = self.convertFilePathToRepoRelativePath(
                    allData.getFile())
                fullCodeWithBug = self.vcs.getFileContents(
                    fileRelativePath, self.commits[self.currentCommitIndex])
                extractor = CodeExtractor(allData)
                extractor.loadCodeFromText(fullCodeWithBug)
                extractor.extractBugCode()
                bugCodeFragment = extractor.getBugCodeFragment()
                fixCodeFragment = ''
                # Encode it
                encodedBugData, initialUnkList = self.coder.encode(
                    bugCodeFragment, checkerData=checkerInfo)
                # Convert to one-hot
                MODEL_X_MAX_LEN = model.get_layer(index=0).input_shape[1]
                if len(encodedBugData) > MODEL_X_MAX_LEN:
                    print(
                        "Bug #{0} - Code too big for model, ignored".format(i))
                    continue
                elif id == -1:
                    print("Bug #{0} - Good to go".format(i))
                    continue
                noZerosToPad = MODEL_X_MAX_LEN - len(encodedBugData)
                if noZerosToPad > 0:
                    encodedBugData = self.coder.applyPadding(
                        encodedBugData, noZerosToPad)
                X = np.zeros((1, MODEL_X_MAX_LEN, self.totalDictionaryLength))
                X[0] = self.coder.convertToOneHot(
                    encodedBugData,
                    np.zeros((MODEL_X_MAX_LEN, self.totalDictionaryLength)))
                # Predict and convert from one-hot
                Y = self.coder.convertFromOneHot(model.predict(X)[0])
                print(Y)
                # Decode
                Y = self.coder.removePadding(Y)
                fixCodeFragment = self.coder.decode(Y, initialUnkList)

                #Verify?
                vStatus = 2
                if config.cfVerifyPrediction:
                    # Apply fix in source code file
                    extractor.applyFix(fixCodeFragment)
                    extractor.saveToFile(allData.getFile())
                    # Run CodeChecker and analyze code
                    self.codeChecker.check(True)
                    resolvedIds = self.getDiffResolvedIds()
                    # Check if ID is resolved in tmp folder
                    isFixed = i in resolvedIds
                    # Set vStatus accordingly
                    if isFixed:
                        vStatus = 1
                    else:
                        vStatus = 0
                #Print
                print("Bug #{0} - summary".format(i))
                print("== Code fragment with bug ==")
                print(bugCodeFragment)
                print("== Suggested fix ==")
                print(fixCodeFragment)
                print("Verification: {0}".format(vLabels[vStatus]))
                a = ' '
                while a != 'y' and a != 'n':
                    a = input("Apply fix? (y/n): ")
                if a == 'y':
                    if not config.cfVerifyPrediction:
                        # Apply fix in source code file
                        extractor.applyFix(fixCodeFragment)
                        extractor.saveToFile(allData.getFile())
                elif config.cfVerifyPrediction:
                    # Revert file contents
                    self.vcs.checkout(self.commits[self.currentCommitIndex])
                print('Done')
        print("All done, exiting...")
コード例 #4
0
 def __init__(self):
     self.vcs = GitProvider(config.getRepoDir())
     self.ccdb = CCDatabase(config.getCcDbFile())
     self.codeChecker = CodeChecker(config.getRepoDir())
コード例 #5
0
 def testDatabaseOpenExistingSuccess(self):
     dbPath = config.getCcDbFile()
     db = CCDatabase(dbPath)
     self.assertEqual(len(db.getAllReports()), 0)
コード例 #6
0

def fix(code, bugData):
    if bugData.getChecker() == 'deadcode.DeadStores':
        return fixDeadStore(code, bugData)
    if bugData.getChecker(
    ) == 'clang-diagnostic-tautological-constant-out-of-range-compare':
        return findTautOORCmp(code, bugData)
    if bugData.getChecker() == 'clang-diagnostic-unused-parameter':
        return fixUnusedParam(code, bugData)
    if bugData.getChecker() == 'clang-diagnostic-constant-conversion':
        return fixConstConv(code, bugData)
    return None


ccdb = CCDatabase(config.getCcDbFile())
db = sqlite3.connect('../Results/db.sqlite')
cursor = db.cursor()
cursor.execute('SELECT * FROM bugs')
dataFromDb = cursor.fetchall()
bugs = []
bugsPerFile = {}
BUG_NOT_PROCESSED = 0
vcs = GitProvider(config.getRepoDir())
checkers = Checkers()
currentCommit = vcs.getAllVersions(config.getBranch())[0]
bugDataList = {}
fileContents = {}
codechecker = CodeChecker(config.getRepoDir())

if len(dataFromDb) > 0:
コード例 #7
0
class TestDbBuilder():
    def __init__(self):
        self.vcs = GitProvider(config.getRepoDir())
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())

    def loadCommitList(self, clean=False):
        self.commits = self.vcs.getAllVersions(config.getBranch())
        if not clean:
            lastCommit = self.db.getLastCommit()
            lastIndex = self.commits.index(lastCommit) + 1
            if lastIndex < len(self.commits) - 1:
                self.commits = self.commits[0:lastIndex]
            self.currentCommitIndex = lastIndex - 1
        else:
            self.currentCommitIndex = len(self.commits)

    def prepareDb(self, clean=False):
        self.db = CFDatabase(config.getCfDbFile())
        if clean:
            self.db.clean()

    def checkoutToNextVersion(self):
        self.currentCommitIndex = self.currentCommitIndex - 1
        if (self.currentCommitIndex < 0):
            return False
        self.vcs.checkout(self.commits[self.currentCommitIndex])
        return True

    def getDiffResolvedIds(self):
        resolved = self.codeChecker.diffResolved(config.getCcRunName(),
                                                 config.getTmpDir(), self.ccdb)
        ids = []
        for bug in resolved:
            ids.append(bug['reportId'])
        return ids

    def convertFilePathToRepoRelativePath(self, path):
        return os.path.relpath(path, config.getRepoDir())

    def extractCode(self, id):
        bugData = self.ccdb.getNotResolvedBugData(id)
        #TODO: Possible improvement for bugData
        if bugData is None:
            #TODO: Implement custom errors
            return None

        fileRelativePath = self.convertFilePathToRepoRelativePath(
            bugData.getFile())
        try:
            fullCodeWithBug = self.vcs.getFileContents(
                fileRelativePath, self.commits[self.currentCommitIndex + 1])
            fullCodeWithoutBug = self.vcs.getFileContents(
                fileRelativePath, self.commits[self.currentCommitIndex])
        except KeyError as extractError:
            return None

        diff = POSIXDiffer().diff(fullCodeWithBug, fullCodeWithoutBug)

        extractor = CodeExtractor(bugData)
        try:
            extractor.extractAll(fullCodeWithBug, diff)
        except ValueError as extractError:
            return None

        bugCodeFragment = extractor.getBugCodeFragment()
        fixCodeFragment = extractor.getFixCodeFragment()

        usedDiffs = extractor.getUsedDiffs()
        #Easy version - ignore bug if none or more than one diff used to fix
        #TODO: Possible improvement here
        if len(usedDiffs) != 1:
            return None
        return entities.FixData(bugCodeFragment, fixCodeFragment,
                                bugData.getChecker(), bugData.getMessage(),
                                bugData.getLine() - bugData.getStartLine())

    def prepareEnv(self, clean=False):
        print('Preparing train db... ', end='')
        self.prepareDb(clean)
        print('done')
        print('Loading commit list... ', end='')
        self.loadCommitList(clean)
        print('done')
        if clean:
            print('Checking out to root... ', end='')
            self.checkoutToNextVersion()
            print('done')
            print('Initial analysis... ', end='')
            self.codeChecker.check(True)
            print('done')
            print('Storing initial results... ', end='')
            self.codeChecker.store(self.commits[self.currentCommitIndex])
            print('done')
            print('Storing version information... ', end='')
            self.db.storeLastCommit(self.commits[self.currentCommitIndex])
            print('done')
            print('Cleaning up tmp directory... ', end='')
            shutil.rmtree(config.getTmpDir())
            print('done')
            print('Cleaning up working directory... ', end='')
            self.codeChecker.clean()
            print('done')

    def findAndStoreFixDataForVersion(self):
        print('Analyzing version',
              self.commits[self.currentCommitIndex],
              '... ',
              end='')
        self.codeChecker.check(True)
        print('done')
        print('Getting list of resolved bugs for version',
              self.commits[self.currentCommitIndex],
              '... ',
              end='')
        ids = self.getDiffResolvedIds()
        print('done')
        bugNo = 1
        allBugs = len(ids)
        anyStored = False
        for id in ids:
            print('Parsing data for bug ({0}/{1}, #{2})...'.format(
                bugNo, allBugs, id),
                  sep='',
                  end='')
            fixData = self.extractCode(id)
            bugNo = bugNo + 1
            print('done')
            if fixData is not None:
                print('Storing fixData... ', end='')
                self.db.store(fixData.getBugCode(), fixData.getFixCode(),
                              fixData.getChecker(), fixData.getMessage(),
                              fixData.getLine())
                anyStored = True
                print('done')
            if bugNo % 100 == 0 and anyStored:
                self.db.commit()
                anyStored = False
        if anyStored:
            self.db.commit()
        print('Storing CodeChecker results for this version... ', end='')
        self.codeChecker.store(self.commits[self.currentCommitIndex])
        print('done')
        print('Storing version information... ', end='')
        self.db.storeLastCommit(self.commits[self.currentCommitIndex])
        print('done')
        print('Cleaning up tmp directory... ', end='')
        shutil.rmtree(config.getTmpDir())
        print('done')
        print('Cleaning up working directory... ', end='')
        self.codeChecker.clean()
        print('done')

    def iterateThroughVcsHistory(self):
        while self.checkoutToNextVersion():
            self.findAndStoreFixDataForVersion()

    def checkoutToTop(self):
        self.vcs.checkout(config.getBranch())

    def build(self, clean=False):
        self.prepareEnv(clean)
        self.iterateThroughVcsHistory()
        self.checkoutToTop()
コード例 #8
0
class FixUnusedParam():
    def __init__(self):
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.code = []
        self.checkers = Checkers()

    def loadCodeFromFile(self):
        with open(self.bugData.getFile(), 'r') as file:
            code = file.readlines()
            self.code = []
            for line in code:
                self.code.append(line.replace("\r\n", "\n"))
            """
            code = file.read()
            noCrLf = code.count("\r\n")
            noCr = code.count("\r") - noCrLf
            noLf = code.count("\n") - noCrLf
            if noCrLf > noCr:
                if noCrLf > noLf:
                    self.lineEnding = "\r\n"
                else:
                    self.lineEnding = "\n"
            else:
                if noCr > noLf:
                    self.lineEnding = "\r"
                else:
                    self.lineEnding = "\n"
            self.code = code.split(self.lineEnding)
            """

    def saveCodeToFile(self):
        with open(self.bugData.getFile(), 'w') as file:
            #file.write(self.lineEnding.join(self.code))
            file.writelines(self.code)

    def fix(self, file):
        fileData = self.ccdb.getFileData(file)
        print(fileData)
        bugs = self.ccdb.getAllBugsForChecker(
            'clang-diagnostic-unused-parameter')
        lines = []
        inserts = 0
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() not in lines:
                    self.loadCodeFromFile()

                    newLine = '// codechecker_intentional [clang-diagnostic-unused-parameter] Suppress\n'
                    self.code.insert(self.bugData.getLine() - 1 + inserts,
                                     newLine)
                    inserts = inserts + 1

                    self.saveCodeToFile()
                    lines = lines + list(
                        range((self.bugData.getLine() - 11),
                              (self.bugData.getLine() + 10)))
                    print("Passed")
                    print(self.bugData.getLine())
                    pass
                else:
                    print("Dismissed")
                    print(self.bugData.getLine())
                    pass
コード例 #9
0
 def __init__(self):
     self.ccdb = CCDatabase(config.getCcDbFile())
     self.codeChecker = CodeChecker(config.getRepoDir())
     self.code = []
     self.checkers = Checkers()
コード例 #10
0
class FixDeadStore():
    def __init__(self):
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.code = []

    def loadCodeFromFile(self):
        with open(self.bugData.getFile(), 'r') as file:
            code = file.readlines()
            self.code = []
            for line in code:
                self.code.append(line.replace("\r\n", "\n"))
            """
            code = file.read()
            noCrLf = code.count("\r\n")
            noCr = code.count("\r") - noCrLf
            noLf = code.count("\n") - noCrLf
            if noCrLf > noCr:
                if noCrLf > noLf:
                    self.lineEnding = "\r\n"
                else:
                    self.lineEnding = "\n"
            else:
                if noCr > noLf:
                    self.lineEnding = "\r"
                else:
                    self.lineEnding = "\n"
            self.code = code.split(self.lineEnding)
            """

    def saveCodeToFile(self):
        with open(self.bugData.getFile(), 'w') as file:
           #file.write(self.lineEnding.join(self.code))
           file.writelines(self.code)
    
    def fix(self, file):
        fileData = self.ccdb.getFileData(file)
        print(fileData)
        bugs = self.ccdb.getAllBugsForChecker('deadcode.DeadStores')
        lines = []
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() not in lines:
                    self.loadCodeFromFile()
                    #lineEnding = self.getLineEnding()
                    if self.bugData.getLine() == 1:
                        self.code = ["\n"] + self.code[1:]
                    elif self.bugData.getLine() == len(self.code):
                        self.code = self.code[:-1] + ["\n"]
                    else:
                        self.code = self.code[0:(self.bugData.getLine() - 1)] + ["\n"] + self.code[self.bugData.getLine():]
                    self.saveCodeToFile()
                    lines = lines + list(range((self.bugData.getLine() - 11), (self.bugData.getLine() + 10)))
                    print("Passed")
                    print(self.bugData.getLine())
                    pass
                else:
                    print("Dismissed")
                    print(self.bugData.getLine())
                    pass
コード例 #11
0
class FixTautOORCmp():
    def __init__(self):
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.code = []
        self.checkers = Checkers()

    def loadCodeFromFile(self):
        with open(self.bugData.getFile(), 'r') as file:
            code = file.readlines()
            self.code = []
            for line in code:
                self.code.append(line.replace("\r\n", "\n"))
            """
            code = file.read()
            noCrLf = code.count("\r\n")
            noCr = code.count("\r") - noCrLf
            noLf = code.count("\n") - noCrLf
            if noCrLf > noCr:
                if noCrLf > noLf:
                    self.lineEnding = "\r\n"
                else:
                    self.lineEnding = "\n"
            else:
                if noCr > noLf:
                    self.lineEnding = "\r"
                else:
                    self.lineEnding = "\n"
            self.code = code.split(self.lineEnding)
            """

    def saveCodeToFile(self):
        with open(self.bugData.getFile(), 'w') as file:
            #file.write(self.lineEnding.join(self.code))
            file.writelines(self.code)

    def findMatchingDefine(self, value):
        patValue = '({0})'
        patName = '[ \t]([0-9a-zA-Z_]+)[ \t]'
        for line in self.code:
            if line[:7] == '#define':
                if re.search(patValue.format(value), line):
                    return re.search(patName, line).group(1)
        return None

    def fix(self, file):
        fileData = self.ccdb.getFileData(file)
        print(fileData)
        bugs = self.ccdb.getAllBugsForChecker(
            'clang-diagnostic-tautological-constant-out-of-range-compare')
        lines = []
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() not in lines:
                    self.loadCodeFromFile()

                    tokens = self.checkers.extractTokensForChecker(
                        'clang-diagnostic-tautological-constant-out-of-range-compare',
                        self.bugData.getMessage())
                    line = self.code[self.bugData.getLine() - 1]
                    pat = "\([^\(]*{0}\)".format(tokens[0]['value'])
                    match = re.search(pat, line)
                    if match is None:
                        pat = "\([^\(]*{0}\)".format(
                            self.findMatchingDefine(tokens[0]['value']))
                        match = re.search(pat, line)
                    match = match.group(0)
                    newLine = line.replace(match,
                                           '({0})'.format(tokens[1]['value']))
                    self.code[self.bugData.getLine() - 1] = newLine

                    self.saveCodeToFile()
                    lines = lines + list(
                        range((self.bugData.getLine() - 11),
                              (self.bugData.getLine() + 10)))
                    print("Passed")
                    print(self.bugData.getLine())
                    pass
                else:
                    print("Dismissed")
                    print(self.bugData.getLine())
                    pass
コード例 #12
0
class FixTautOORCmp():
    def __init__(self):
        self.ccdb = CCDatabase(config.getCcDbFile())
        self.codeChecker = CodeChecker(config.getRepoDir())
        self.code = []
        self.checkers = Checkers()

    def loadCodeFromFile(self):
        with open(self.bugData.getFile(), 'r') as file:
            code = file.readlines()
            self.code = []
            for line in code:
                self.code.append(line.replace("\r\n", "\n"))

    def saveCodeToFile(self):
        with open(self.bugData.getFile(), 'w') as file:
           #file.write(self.lineEnding.join(self.code))
           file.writelines(self.code)
    
    def findMatchingDefine(self, value):
        patValue = '({0})'
        patName = '[ \t]([0-9a-zA-Z_]+)[ \t]'
        for line in self.code:
            if line[:7] == '#define':
                if re.search(patValue.format(value), line):
                    return re.search(patName, line).group(1)
        return None
    
    def fix(self, file):
        fileData = self.ccdb.getFileData(file)
        print(fileData)
        bugs = self.ccdb.getAllBugsForChecker('clang-diagnostic-constant-conversion')
        lines = []
        linesSingle = {}
        linesToSuppress = []
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() in linesSingle:
                    linesSingle[self.bugData.getLine()] += 1
                else:
                    linesSingle[self.bugData.getLine()] = 1
        for k in linesSingle:
            if linesSingle[k] > 5:
                linesToSuppress.append(k)
        inserts = 0
        for bug in bugs:
            if bug[2] == fileData[-1][0]:
                self.bugData = self.ccdb.getBugData(bug[0])
                if self.bugData.getLine() not in lines:
                    self.loadCodeFromFile()

                    if self.bugData.getLine() not in linesToSuppress:
                        tokens = self.checkers.extractTokensForChecker('clang-diagnostic-constant-conversion', self.bugData.getMessage())
                        test = tokens
                        line = self.code[self.bugData.getLine() - 1 + inserts]
                        newLine = line.replace(tokens[0]['value'], '({0}){1}'.format(tokens[1]['value'], tokens[0]['value']))
                        if line == newLine:
                            tokens[0]['value'] = self.findMatchingDefine(tokens[0]['value'])
                            if tokens[0]['value'] is not None:
                                newLine = line.replace(tokens[0]['value'], '({0}){1}'.format(tokens[1]['value'], tokens[0]['value']))
                        if line == newLine:
                            s = re.search('= (.*);', line)
                            expr = s.group(1)
                            newLine = line.replace(expr, '({0})({1})'.format(tokens[1]['value'], expr))
                        self.code[self.bugData.getLine() - 1 + inserts] = newLine
                    else:
                        line = self.code[self.bugData.getLine() - 1 + inserts]
                        self.code[self.bugData.getLine() - 1 + inserts] = '// codechecker_intentional [clang-diagnostic-constant-conversion] Suppress\n{0}'.format(line)
                        inserts += 1

                    self.saveCodeToFile()
                    lines = lines + list(range((self.bugData.getLine() - 11), (self.bugData.getLine() + 10)))
                    
                    print("Passed, suppressed: {0}".format(self.bugData.getLine() in linesToSuppress))
                    print(self.bugData.getLine())
                    pass
                else:
                    print("Dismissed")
                    print(self.bugData.getLine())
                    pass