Ejemplo n.º 1
0
def pinpoint(itest, logPrefix, jsEngine, engineFlags, infilename, bisectRepo,
             buildOptionsStr, targetTime, suspiciousLevel):
    """Run Lithium and autobisect.

    itest must be an array of the form [module, ...] where module is an interestingness module.
    The module's "interesting" function must accept [...] + [jsEngine] + engineFlags + infilename
    (If it's not prepared to accept engineFlags, engineFlags must be empty.)
    """
    lithArgs = itest + [jsEngine] + engineFlags + [infilename]

    (lithResult, lithDetails) = strategicReduction(logPrefix, infilename,
                                                   lithArgs, targetTime,
                                                   suspiciousLevel)

    print()
    print(
        "Done running Lithium on the part in between DDBEGIN and DDEND. To reproduce, run:"
    )
    print(
        sps.shellify(
            [sys.executable, "-u", "-m", "lithium", "--strategy=check-only"] +
            lithArgs))
    print()

    if bisectRepo is not "none" and targetTime >= 3 * 60 * 60 and buildOptionsStr is not None:
        if platform.uname()[2] == 'XP':
            print(
                "Not pinpointing to exact changeset since autoBisect does not work well in WinXP."
            )
        elif testJsShellOrXpcshell(jsEngine) != "xpcshell":
            autobisectCmd = ([sys.executable, autobisectpy] +
                             ["-b", buildOptionsStr] +
                             ["-p", ' '.join(engineFlags + [infilename])] +
                             ["-i"] + itest)
            print(sps.shellify(autobisectCmd))
            autoBisectLogFilename = logPrefix + "-autobisect.txt"
            subprocess.call(autobisectCmd,
                            stdout=open(autoBisectLogFilename, "w"),
                            stderr=subprocess.STDOUT)
            print("Done running autobisect. Log: %s" % autoBisectLogFilename)

            with open(autoBisectLogFilename, 'rb') as f:
                lines = f.readlines()
                autoBisectLog = fileManipulation.truncateMid(
                    lines, 50, ["..."])
    else:
        autoBisectLog = []

    return (lithResult, lithDetails, autoBisectLog)
Ejemplo n.º 2
0
def pinpoint(itest, logPrefix, jsEngine, engineFlags, infilename, bisectRepo, buildOptionsStr, targetTime, suspiciousLevel):
    """
    Run Lithium and autobisect.

    itest must be an array of the form [module, ...] where module is an interestingness module.
    The module's "interesting" function must accept [...] + [jsEngine] + engineFlags + infilename
    (If it's not prepared to accept engineFlags, engineFlags must be empty.)
    """
    lithArgs = itest + [jsEngine] + engineFlags + [infilename]

    (lithResult, lithDetails) = strategicReduction(logPrefix, infilename, lithArgs, targetTime, suspiciousLevel)

    print "\nDone running Lithium on the part in between DDBEGIN and DDEND. To reproduce, run:"
    print sps.shellify([lithiumpy, "--strategy=check-only"] + lithArgs) + '\n'

    if bisectRepo is not "none" and targetTime >= 3*60*60 and buildOptionsStr is not None:
        if platform.uname()[2] == 'XP':
            print 'Not pinpointing to exact changeset since autoBisect does not work well in WinXP.'
        elif testJsShellOrXpcshell(jsEngine) != "xpcshell":
            autobisectCmd = (
                [sys.executable, autobisectpy] +
                ["-b", buildOptionsStr] +
                ["-p", ' '.join(engineFlags + [infilename])] +
                ["-i"] + itest
            )
            print sps.shellify(autobisectCmd)
            autoBisectLogFilename = logPrefix + "-autobisect.txt"
            subprocess.call(autobisectCmd, stdout=open(autoBisectLogFilename, "w"), stderr=subprocess.STDOUT)
            print "Done running autobisect. Log: " + autoBisectLogFilename

            with open(autoBisectLogFilename, 'rb') as f:
                lines = f.readlines()
                autoBisectLog = fileManipulation.truncateMid(lines, 50, ["..."])
    else:
        autoBisectLog = []

    return (lithResult, lithDetails, autoBisectLog)
Ejemplo n.º 3
0
    def __init__(self, cfg, url, logPrefix, extraPrefs="", quiet=False, leaveProfile=False):
        """Run Firefox once, detect bugs, and determine a 'level' based on the most severe unknown bug."""

        profileDir = mkdtemp(prefix="domfuzz-rdf-profile")
        createDOMFuzzProfile(profileDir)
        writePrefs(profileDir, extraPrefs)

        runBrowserArgs = [cfg.dirs.reftestScriptDir, cfg.dirs.utilityDir, profileDir]

        assert logPrefix  # :(
        leakLogFile = logPrefix + "-leaks.txt"

        runbrowserpy = [sys.executable, "-u", os.path.join(THIS_SCRIPT_DIRECTORY, "runbrowser.py")]
        runbrowser = subprocess.Popen(
            runbrowserpy + ["--leak-log-file=" + leakLogFile] + cfg.runBrowserOptions + runBrowserArgs + [url],
            stdin=None,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,  # Hmm, CrashInfo.fromRawCrashData expects them separate, but I like them together...
            env=cfg.env,
            close_fds=close_fds
        )

        alh = AmissLogHandler(cfg.knownPath, cfg.options.valgrind)

        # Bug 718208
        if extraPrefs.find("inflation") != -1:
            alh.expectedToRenderInconsistently = True

        statusLinePrefix = "RUNBROWSER INFO | runbrowser.py | runApp: exited with status "
        status = -9000

        # NB: not using 'for line in runbrowser.stdout' because that uses a hidden buffer
        # see http://docs.python.org/library/stdtypes.html#file.next
        while True:
            line = runbrowser.stdout.readline()
            if line != '':
                line = alh.processLine(line)
                if not quiet:
                    print line,
                if line.startswith(statusLinePrefix):
                    status = int(line[len(statusLinePrefix):])
            else:
                break

        lev = DOM_FINE

        if alh.mallocFailure:
            lev = max(lev, DOM_NEW_ASSERT_OR_CRASH)
        if alh.fuzzerComplained or alh.sawChromeFailure:
            lev = max(lev, DOM_FUZZER_COMPLAINED)
        if alh.sawValgrindComplaint:
            lev = max(lev, DOM_VG_AMISS)
        if alh.sawNewNonfatalAssertion:
            lev = max(lev, DOM_NEW_ASSERT_OR_CRASH)

        # Leak stuff
        if 'user_pref("layers.use-deprecated-textures", true);' in extraPrefs:
            # Bug 933569
            # Doing the change *here* only works because this is a small leak that shouldn't affect the reads in alh
            alh.expectedToLeak = True
        if 'user_pref("gfx.downloadable_fonts.disable_cache", true);' in extraPrefs:
            # Bug 1258031
            # This is a large leak. I don't remember what the comment above is about.
            alh.expectedToLeak = True
        if os.path.exists(leakLogFile) and status == 0 and detect_leaks.amiss(cfg.knownPath, leakLogFile, verbose=not quiet) and not alh.expectedToLeak:
            alh.printAndLog(DOMI_MARKER + "Leak (trace-refcnt)")
            alh.printAndLog("Leak details: " + os.path.basename(leakLogFile))
            lev = max(lev, DOM_UNEXPECTED_LEAK)
        else:
            if alh.sawOMGLEAK and not alh.expectedToLeak:
                lev = max(lev, DOM_UNEXPECTED_LEAK)
            if leakLogFile:
                # Remove the main leak log file, plus any plugin-process leak log files
                for f in glob.glob(leakLogFile + "*"):
                    os.remove(f)

        # Do various stuff based on how the process exited
        if alh.timedOut:
            if alh.expectedToHang or cfg.options.valgrind:
                alh.printAndLog("%%% An expected hang")
            else:
                alh.printAndLog(DOMI_MARKER + "Unexpected hang")
                lev = max(lev, DOM_UNEXPECTED_HANG)
        elif status < 0 and os.name == 'posix':
            signum = -status
            signame = getSignalName(signum, "unknown signal")
            print "DOMFUZZ INFO | domInteresting.py | Terminated by signal " + str(signum) + " (" + signame + ")"
        elif status == 1:
            alh.printAndLog("%%% Exited with status 1 (crash?)")
        elif status == -2147483645 and sps.isWin:
            alh.printAndLog("%%% Exited with status -2147483645 (plugin issue, bug 867263?)")
        elif status != 0:
            alh.printAndLog(DOMI_MARKER + "Abnormal exit (status %d)" % status)
            lev = max(lev, DOM_ABNORMAL_EXIT)

        # Always look for crash information in stderr.
        linesWithoutLineBreaks = [s.rstrip() for s in alh.fullLog]
        linesWithoutLineBreaks = fileManipulation.truncateMid(linesWithoutLineBreaks, 5000, ["..."])
        crashInfo = CrashInfo.CrashInfo.fromRawCrashData([], linesWithoutLineBreaks, cfg.pc)

        # If the program crashed but we didn't find crash info in stderr (breakpad/asan),
        # poll for a core file (to feed to gdb) or log from the Mac crash reporter.
        if isinstance(crashInfo, CrashInfo.NoCrashInfo) and status < 0 and os.name == 'posix':
            signum = -status
            if signum != signal.SIGKILL and signum != signal.SIGTERM:
                wantStack = True
                assert alh.theapp
                crashLog = sps.grabCrashLog(alh.theapp, alh.pid, logPrefix, wantStack)
                if crashLog:
                    with open(crashLog) as f:
                        auxCrashData = f.readlines()
                    crashInfo = CrashInfo.CrashInfo.fromRawCrashData([], linesWithoutLineBreaks, cfg.pc, auxCrashData=auxCrashData)
                else:
                    alh.printAndLog(DOMI_MARKER + "The browser crashed, but did not leave behind any crash information!")
                    lev = max(lev, DOM_NEW_ASSERT_OR_CRASH)

        createCollector.printCrashInfo(crashInfo)
        if not isinstance(crashInfo, CrashInfo.NoCrashInfo):
            lev = max(lev, DOM_NEW_ASSERT_OR_CRASH)

        match = cfg.collector.search(crashInfo)
        if match[0] is not None:
            createCollector.printMatchingSignature(match)
            lev = DOM_FINE

        if lev > DOM_FINE:
            with open(logPrefix + "-output.txt", "w") as outlog:
                outlog.writelines(alh.fullLog)
            subprocess.call(["gzip", logPrefix + "-output.txt"])
            with open(logPrefix + "-summary.txt", "w") as summaryLogFile:
                summaryLogFile.writelines(alh.summaryLog)

        if lev == DOM_FINE:
            removeIfExists(logPrefix + "-core.gz")
            removeIfExists(logPrefix + "-crash.txt")

        if not leaveProfile:
            shutil.rmtree(profileDir)

        print "DOMFUZZ INFO | domInteresting.py | " + str(lev)

        self.level = lev
        self.lines = alh.fullLog
        self.crashInfo = crashInfo