def __init__(self, options, runthis, logPrefix, inCompareJIT): pathToBinary = runthis[0] # This relies on the shell being a local one from compileShell.py: # Ignore trailing ".exe" in Win, also abspath makes it work w/relative paths like './js' pc = ProgramConfiguration.fromBinary( os.path.abspath(pathToBinary).split('.')[0]) pc.addProgramArguments(runthis[1:-1]) if options.valgrind: runthis = (inspectShell.constructVgCmdList( errorCode=VALGRIND_ERROR_EXIT_CODE) + valgrindSuppressions(options.knownPath) + runthis) preexec_fn = ulimitSet if os.name == 'posix' else None runinfo = timed_run.timed_run(runthis, options.timeout, logPrefix, preexec_fn=preexec_fn) lev = JS_FINE issues = [] auxCrashData = [] # FuzzManager expects a list of strings rather than an iterable, so bite the # bullet and 'readlines' everything into memory. with open(logPrefix + "-out.txt") as f: out = f.readlines() with open(logPrefix + "-err.txt") as f: err = f.readlines() if options.valgrind and runinfo.return_code == VALGRIND_ERROR_EXIT_CODE: issues.append("valgrind reported an error") lev = max(lev, JS_VG_AMISS) valgrindErrorPrefix = "==" + str(runinfo.pid) + "==" for line in err: if valgrindErrorPrefix and line.startswith( valgrindErrorPrefix): issues.append(line.rstrip()) elif runinfo.sta == timed_run.CRASHED: if sps.grabCrashLog(runthis[0], runinfo.pid, logPrefix, True): with open(logPrefix + "-crash.txt") as f: auxCrashData = [line.strip() for line in f.readlines()] elif detect_malloc_errors.amiss(logPrefix): issues.append("malloc error") lev = max(lev, JS_NEW_ASSERT_OR_CRASH) elif runinfo.return_code == 0 and not inCompareJIT: # We might have(??) run jsfunfuzz directly, so check for special kinds of bugs for line in out: if line.startswith("Found a bug: ") and not ("NestTest" in line and oomed(err)): lev = JS_DECIDED_TO_EXIT issues.append(line.rstrip()) if options.shellIsDeterministic and not understoodJsfunfuzzExit( out, err) and not oomed(err): issues.append("jsfunfuzz didn't finish") lev = JS_DID_NOT_FINISH # Copy non-crash issues to where FuzzManager's "AssertionHelper.py" can see it. if lev != JS_FINE: for issue in issues: err.append("[Non-crash bug] " + issue) # Finally, make a CrashInfo object and parse stack traces for asan/crash/assertion bugs crashInfo = CrashInfo.CrashInfo.fromRawCrashData( out, err, pc, auxCrashData=auxCrashData) createCollector.printCrashInfo(crashInfo) # We only care about crashes and assertion failures on shells with no symbols # Note that looking out for the Assertion failure message is highly SpiderMonkey-specific if not isinstance(crashInfo, CrashInfo.NoCrashInfo) or \ 'Assertion failure: ' in str(crashInfo.rawStderr) or \ 'Segmentation fault' in str(crashInfo.rawStderr) or \ 'Bus error' in str(crashInfo.rawStderr): lev = max(lev, JS_NEW_ASSERT_OR_CRASH) match = options.collector.search(crashInfo) if match[0] is not None: createCollector.printMatchingSignature(match) lev = JS_FINE print("%s | %s" % (logPrefix, summaryString(issues, lev, runinfo.elapsedtime))) if lev != JS_FINE: fileManipulation.writeLinesToFile([ 'Number: ' + logPrefix + '\n', 'Command: ' + sps.shellify(runthis) + '\n' ] + ['Status: ' + i + "\n" for i in issues], logPrefix + '-summary.txt') self.lev = lev self.out = out self.err = err self.issues = issues self.crashInfo = crashInfo self.match = match self.runinfo = runinfo self.return_code = runinfo.return_code
def baseLevel(runthis, timeout, knownPath, logPrefix, valgrind=False): if valgrind: runthis = ( inspectShell.constructVgCmdList(errorCode=VALGRIND_ERROR_EXIT_CODE) + valgrindSuppressions(knownPath) + runthis ) preexec_fn = ulimitSet if os.name == "posix" else None runinfo = timedRun.timed_run(runthis, timeout, logPrefix, preexec_fn=preexec_fn) sta = runinfo.sta if sta == timedRun.CRASHED: sps.grabCrashLog(runthis[0], runinfo.pid, logPrefix, True) lev = JS_FINE issues = [] sawAssertion = False if detect_malloc_errors.amiss(logPrefix): issues.append("malloc error") lev = max(lev, JS_MALLOC_ERROR) if valgrind and runinfo.rc == VALGRIND_ERROR_EXIT_CODE: issues.append("valgrind reported an error") lev = max(lev, JS_VG_AMISS) valgrindErrorPrefix = "==" + str(runinfo.pid) + "==" else: valgrindErrorPrefix = None def printNote(note): print "%%% " + note crashWatcher = detect_crashes.CrashWatcher(knownPath, False, printNote) with open(logPrefix + "-err.txt", "rb") as err: for line in err: assertionSeverity, assertionIsNew = detect_assertions.scanLine(knownPath, line) crashWatcher.processOutputLine(line.rstrip()) if assertionIsNew: issues.append(line.rstrip()) lev = max(lev, JS_NEW_ASSERT_OR_CRASH) if assertionSeverity == detect_assertions.FATAL_ASSERT: sawAssertion = True lev = max(lev, JS_KNOWN_CRASH) if valgrindErrorPrefix and line.startswith(valgrindErrorPrefix): issues.append(line.rstrip()) if sta == timedRun.CRASHED and not sawAssertion: crashWatcher.readCrashLog(logPrefix + "-crash.txt") if sawAssertion: # Ignore the crash log, since we've already seen a new assertion failure. pass elif crashWatcher.crashProcessor: crashFrom = " (from " + crashWatcher.crashProcessor + ")" if crashWatcher.crashIsKnown: issues.append("known crash" + crashFrom) lev = max(lev, JS_KNOWN_CRASH) else: issues.append("unknown crash" + crashFrom) lev = max(lev, JS_NEW_ASSERT_OR_CRASH) elif sta == timedRun.TIMED_OUT: issues.append("timed out") lev = max(lev, JS_TIMED_OUT) elif sta == timedRun.ABNORMAL and not (valgrind and runinfo.rc == VALGRIND_ERROR_EXIT_CODE): issues.append("abnormal exit") lev = max(lev, JS_ABNORMAL_EXIT) return (lev, issues, runinfo)
def __init__(self, options, runthis, logPrefix, inCompareJIT): pathToBinary = runthis[0] # This relies on the shell being a local one from compileShell.py: pc = ProgramConfiguration.fromBinary(pathToBinary.split('.')[0]) # Ignore trailing ".exe" in Win pc.addProgramArguments(runthis[1:-1]) if options.valgrind: runthis = ( inspectShell.constructVgCmdList(errorCode=VALGRIND_ERROR_EXIT_CODE) + valgrindSuppressions(options.knownPath) + runthis) preexec_fn = ulimitSet if os.name == 'posix' else None runinfo = timedRun.timed_run(runthis, options.timeout, logPrefix, preexec_fn=preexec_fn) lev = JS_FINE issues = [] auxCrashData = [] # FuzzManager expects a list of strings rather than an iterable, so bite the # bullet and 'readlines' everything into memory. with open(logPrefix + "-out.txt") as f: out = f.readlines() with open(logPrefix + "-err.txt") as f: err = f.readlines() if options.valgrind and runinfo.rc == VALGRIND_ERROR_EXIT_CODE: issues.append("valgrind reported an error") lev = max(lev, JS_VG_AMISS) valgrindErrorPrefix = "==" + str(runinfo.pid) + "==" for line in err: if valgrindErrorPrefix and line.startswith(valgrindErrorPrefix): issues.append(line.rstrip()) elif runinfo.sta == timedRun.CRASHED: if sps.grabCrashLog(runthis[0], runinfo.pid, logPrefix, True): with open(logPrefix + "-crash.txt") as f: auxCrashData = [line.strip() for line in f.readlines()] elif detect_malloc_errors.amiss(logPrefix): issues.append("malloc error") lev = max(lev, JS_NEW_ASSERT_OR_CRASH) elif runinfo.rc == 0 and not inCompareJIT: # We might have(??) run jsfunfuzz directly, so check for special kinds of bugs for line in out: if line.startswith("Found a bug: ") and not ("NestTest" in line and oomed(err)): lev = JS_DECIDED_TO_EXIT issues.append(line.rstrip()) if options.shellIsDeterministic and not understoodJsfunfuzzExit(out, err) and not oomed(err): issues.append("jsfunfuzz didn't finish") lev = JS_DID_NOT_FINISH # Copy non-crash issues to where FuzzManager's "AssertionHelper.py" can see it. if lev != JS_FINE: for issue in issues: err.append("[Non-crash bug] " + issue) # Finally, make a CrashInfo object and parse stack traces for asan/crash/assertion bugs crashInfo = CrashInfo.CrashInfo.fromRawCrashData(out, err, pc, auxCrashData=auxCrashData) createCollector.printCrashInfo(crashInfo) if not isinstance(crashInfo, CrashInfo.NoCrashInfo): lev = max(lev, JS_NEW_ASSERT_OR_CRASH) match = options.collector.search(crashInfo) if match[0] is not None: createCollector.printMatchingSignature(match) lev = JS_FINE print logPrefix + " | " + summaryString(issues, lev, runinfo.elapsedtime) if lev != JS_FINE: fileManipulation.writeLinesToFile( ['Number: ' + logPrefix + '\n', 'Command: ' + sps.shellify(runthis) + '\n'] + ['Status: ' + i + "\n" for i in issues], logPrefix + '-summary.txt') self.lev = lev self.out = out self.err = err self.issues = issues self.crashInfo = crashInfo self.match = match self.runinfo = runinfo self.rc = runinfo.rc
def baseLevel(runthis, timeout, knownPath, logPrefix, valgrind=False): if valgrind: runthis = (inspectShell.constructVgCmdList( errorCode=VALGRIND_ERROR_EXIT_CODE) + valgrindSuppressions(knownPath) + runthis) preexec_fn = ulimitSet if os.name == 'posix' else None runinfo = timedRun.timed_run(runthis, timeout, logPrefix, preexec_fn=preexec_fn) sta = runinfo.sta if sta == timedRun.CRASHED: sps.grabCrashLog(runthis[0], runinfo.pid, logPrefix, True) lev = JS_FINE issues = [] sawAssertion = False if detect_malloc_errors.amiss(logPrefix): issues.append("malloc error") lev = max(lev, JS_MALLOC_ERROR) if valgrind and runinfo.rc == VALGRIND_ERROR_EXIT_CODE: issues.append("valgrind reported an error") lev = max(lev, JS_VG_AMISS) valgrindErrorPrefix = "==" + str(runinfo.pid) + "==" else: valgrindErrorPrefix = None def printNote(note): print "%%% " + note crashWatcher = detect_crashes.CrashWatcher(knownPath, False, printNote) with open(logPrefix + "-err.txt", "rb") as err: for line in err: assertionSeverity, assertionIsNew = detect_assertions.scanLine( knownPath, line) crashWatcher.processOutputLine(line.rstrip()) if assertionIsNew: issues.append(line.rstrip()) lev = max(lev, JS_NEW_ASSERT_OR_CRASH) if assertionSeverity == detect_assertions.FATAL_ASSERT: sawAssertion = True lev = max(lev, JS_KNOWN_CRASH) if valgrindErrorPrefix and line.startswith(valgrindErrorPrefix): issues.append(line.rstrip()) if sta == timedRun.CRASHED and not sawAssertion: crashWatcher.readCrashLog(logPrefix + "-crash.txt") if sawAssertion: # Ignore the crash log, since we've already seen a new assertion failure. pass elif crashWatcher.crashProcessor: crashFrom = " (from " + crashWatcher.crashProcessor + ")" if crashWatcher.crashIsKnown: issues.append("known crash" + crashFrom) lev = max(lev, JS_KNOWN_CRASH) else: issues.append("unknown crash" + crashFrom) lev = max(lev, JS_NEW_ASSERT_OR_CRASH) elif sta == timedRun.TIMED_OUT: issues.append("timed out") lev = max(lev, JS_TIMED_OUT) elif sta == timedRun.ABNORMAL and not (valgrind and runinfo.rc == VALGRIND_ERROR_EXIT_CODE): issues.append("abnormal exit") lev = max(lev, JS_ABNORMAL_EXIT) return (lev, issues, runinfo)