Example #1
0
def many_timed_runs(targetTime, wtmpDir, args):
    options = parseOpts(args)
    engineFlags = options.engineFlags  # engineFlags is overwritten later if --random-flags is set.
    startTime = time.time()

    if os.path.isdir(sps.normExpUserPath(options.repo)):
        regressionTestListFile = sps.normExpUserPath(
            os.path.join(wtmpDir, "regression-tests.list"))
        with open(regressionTestListFile, "wb") as f:
            for fn in inTreeRegressionTests(options.repo):
                f.write(fn + "\n")
        regressionTestPrologue = makeRegressionTestPrologue(
            options.repo, regressionTestListFile)
    else:
        regressionTestPrologue = ""

    fuzzjs = sps.normExpUserPath(os.path.join(wtmpDir, "jsfunfuzz.js"))
    linkFuzzer(fuzzjs, options.repo, regressionTestPrologue)

    iteration = 0
    while True:
        if targetTime and time.time() > startTime + targetTime:
            print "Out of time!"
            os.remove(fuzzjs)
            if len(os.listdir(wtmpDir)) == 0:
                os.rmdir(wtmpDir)
            return (lithOps.HAPPY, None)

        # Construct command needed to loop jsfunfuzz fuzzing.
        jsInterestingArgs = []
        jsInterestingArgs.append('--timeout=' + str(options.timeout))
        if options.valgrind:
            jsInterestingArgs.append('--valgrind')
        jsInterestingArgs.append(options.knownPath)
        jsInterestingArgs.append(options.jsEngine)
        if options.randomFlags:
            engineFlags = shellFlags.randomFlagSet(options.jsEngine)
            jsInterestingArgs.extend(engineFlags)
        jsInterestingArgs.extend(
            ['-e', 'maxRunTime=' + str(options.timeout * (1000 / 2))])
        jsInterestingArgs.extend(['-f', fuzzjs])
        jsunhappyOptions = jsInteresting.parseOptions(jsInterestingArgs)

        iteration += 1
        logPrefix = sps.normExpUserPath(
            os.path.join(wtmpDir, "w" + str(iteration)))

        level = jsInteresting.jsfunfuzzLevel(jsunhappyOptions, logPrefix)

        if level != jsInteresting.JS_FINE:
            showtail(logPrefix + "-out.txt")
            showtail(logPrefix + "-err.txt")

            # splice jsfunfuzz.js with `grep FRC wN-out`
            filenameToReduce = logPrefix + "-reduced.js"
            [before, after] = fileManipulation.fuzzSplice(fuzzjs)

            with open(logPrefix + '-out.txt', 'rb') as f:
                newfileLines = before + [
                    l.replace('/*FRC*/', '')
                    for l in fileManipulation.linesStartingWith(f, "/*FRC*/")
                ] + after
            fileManipulation.writeLinesToFile(newfileLines,
                                              logPrefix + "-orig.js")
            fileManipulation.writeLinesToFile(newfileLines, filenameToReduce)

            # Run Lithium and autobisect (make a reduced testcase and find a regression window)
            itest = [interestingpy]
            if options.valgrind:
                itest.append("--valgrind")
            itest.append("--minlevel=" + str(level))
            itest.append("--timeout=" + str(options.timeout))
            itest.append(options.knownPath)
            (lithResult, lithDetails) = pinpoint.pinpoint(
                itest, logPrefix, options.jsEngine, engineFlags,
                filenameToReduce, options.repo, options.buildOptionsStr,
                targetTime, level)
            if targetTime:
                return (lithResult, lithDetails)

        else:
            shellIsDeterministic = inspectShell.queryBuildConfiguration(
                options.jsEngine, 'more-deterministic')
            flagsAreDeterministic = "--dump-bytecode" not in engineFlags and '-D' not in engineFlags
            if options.useCompareJIT and level == jsInteresting.JS_FINE and \
                    shellIsDeterministic and flagsAreDeterministic:
                linesToCompare = jitCompareLines(logPrefix + '-out.txt',
                                                 "/*FCM*/")
                jitcomparefilename = logPrefix + "-cj-in.js"
                fileManipulation.writeLinesToFile(linesToCompare,
                                                  jitcomparefilename)
                (lithResult, lithDetails) = compareJIT.compareJIT(
                    options.jsEngine, engineFlags, jitcomparefilename,
                    logPrefix + "-cj", options.knownPath, options.repo,
                    options.buildOptionsStr, options.timeout, targetTime)
                if lithResult == lithOps.HAPPY:
                    os.remove(jitcomparefilename)
                if targetTime and lithResult != lithOps.HAPPY:
                    jsInteresting.deleteLogs(logPrefix)
                    return (lithResult, lithDetails)
            jsInteresting.deleteLogs(logPrefix)
Example #2
0
def many_timed_runs(targetTime, wtmpDir, args, collector):
    options = parseOpts(args)
    engineFlags = options.engineFlags  # engineFlags is overwritten later if --random-flags is set.
    startTime = time.time()

    if os.path.isdir(sps.normExpUserPath(options.repo)):
        regressionTestListFile = sps.normExpUserPath(os.path.join(wtmpDir, "regression-tests.list"))
        with open(regressionTestListFile, "wb") as f:
            for fn in inTreeRegressionTests(options.repo):
                f.write(fn + "\n")
        regressionTestPrologue = makeRegressionTestPrologue(options.repo, regressionTestListFile)
    else:
        regressionTestPrologue = ""

    fuzzjs = sps.normExpUserPath(os.path.join(wtmpDir, "jsfunfuzz.js"))
    linkFuzzer(fuzzjs, options.repo, regressionTestPrologue)

    iteration = 0
    while True:
        if targetTime and time.time() > startTime + targetTime:
            print "Out of time!"
            os.remove(fuzzjs)
            if len(os.listdir(wtmpDir)) == 0:
                os.rmdir(wtmpDir)
            break

        # Construct command needed to loop jsfunfuzz fuzzing.
        jsInterestingArgs = []
        jsInterestingArgs.append('--timeout=' + str(options.timeout))
        if options.valgrind:
            jsInterestingArgs.append('--valgrind')
        jsInterestingArgs.append(options.knownPath)
        jsInterestingArgs.append(options.jsEngine)
        if options.randomFlags:
            engineFlags = shellFlags.randomFlagSet(options.jsEngine)
            jsInterestingArgs.extend(engineFlags)
        jsInterestingArgs.extend(['-e', 'maxRunTime=' + str(options.timeout*(1000/2))])
        jsInterestingArgs.extend(['-f', fuzzjs])
        jsInterestingOptions = jsInteresting.parseOptions(jsInterestingArgs)

        iteration += 1
        logPrefix = sps.normExpUserPath(os.path.join(wtmpDir, "w" + str(iteration)))

        res = jsInteresting.ShellResult(jsInterestingOptions, jsInterestingOptions.jsengineWithArgs, logPrefix, False)

        if res.lev != jsInteresting.JS_FINE:
            showtail(logPrefix + "-out.txt")
            showtail(logPrefix + "-err.txt")

            # splice jsfunfuzz.js with `grep FRC wN-out`
            filenameToReduce = logPrefix + "-reduced.js"
            [before, after] = fileManipulation.fuzzSplice(fuzzjs)

            with open(logPrefix + '-out.txt', 'rb') as f:
                newfileLines = before + [l.replace('/*FRC*/', '') for l in fileManipulation.linesStartingWith(f, "/*FRC*/")] + after
            fileManipulation.writeLinesToFile(newfileLines, logPrefix + "-orig.js")
            fileManipulation.writeLinesToFile(newfileLines, filenameToReduce)

            # Run Lithium and autobisect (make a reduced testcase and find a regression window)
            itest = [interestingpy]
            if options.valgrind:
                itest.append("--valgrind")
            itest.append("--minlevel=" + str(res.lev))
            itest.append("--timeout=" + str(options.timeout))
            itest.append(options.knownPath)
            (lithResult, lithDetails, autoBisectLog) = pinpoint.pinpoint(itest, logPrefix, options.jsEngine, engineFlags, filenameToReduce,
                                                                         options.repo, options.buildOptionsStr, targetTime, res.lev)

            # Upload with final output
            if lithResult == lithOps.LITH_FINISHED:
                fargs = jsInterestingOptions.jsengineWithArgs[:-1] + [filenameToReduce]
                retestResult = jsInteresting.ShellResult(jsInterestingOptions, fargs, logPrefix + "-final", False)
                if retestResult.lev > jsInteresting.JS_FINE:
                    res = retestResult
                    quality = 0
                else:
                    quality = 6
            else:
                quality = 10

            # ddsize = lithOps.ddsize(filenameToReduce)
            print "Submitting " + filenameToReduce + " (quality=" + str(quality) + ") at " + sps.dateStr()

            metadata = {}
            if autoBisectLog:
                metadata = {"autoBisectLog": ''.join(autoBisectLog)}
            collector.submit(res.crashInfo, filenameToReduce, quality, metaData=metadata)
            print "Submitted " + filenameToReduce

        else:
            flagsAreDeterministic = "--dump-bytecode" not in engineFlags and '-D' not in engineFlags
            if options.useCompareJIT and res.lev == jsInteresting.JS_FINE and \
                    jsInterestingOptions.shellIsDeterministic and flagsAreDeterministic:
                linesToCompare = jitCompareLines(logPrefix + '-out.txt', "/*FCM*/")
                jitcomparefilename = logPrefix + "-cj-in.js"
                fileManipulation.writeLinesToFile(linesToCompare, jitcomparefilename)
                anyBug = compareJIT.compareJIT(options.jsEngine, engineFlags, jitcomparefilename,
                                               logPrefix + "-cj", options.repo,
                                               options.buildOptionsStr, targetTime, jsInterestingOptions)
                if not anyBug:
                    os.remove(jitcomparefilename)

            jsInteresting.deleteLogs(logPrefix)
Example #3
0
def compareLevel(jsEngine, flags, infilename, logPrefix, options, showDetailedDiffs, quickMode):
    # options dict must be one we can pass to jsInteresting.ShellResult
    # we also use it directly for knownPath, timeout, and collector
    # Return: (lev, crashInfo) or (jsInteresting.JS_FINE, None)

    combos = shellFlags.basicFlagSets(jsEngine)

    if quickMode:
        # Only used during initial fuzzing. Allowed to have false negatives.
        combos = [combos[0]]

    if len(flags):
        combos.append(flags)

    commands = [[jsEngine] + combo + [infilename] for combo in combos]

    for i in range(0, len(commands)):
        prefix = logPrefix + "-r" + str(i)
        command = commands[i]
        r = jsInteresting.ShellResult(options, command, prefix, True)

        oom = jsInteresting.oomed(r.err)
        r.err = ignoreSomeOfStderr(r.err)

        if (r.rc == 1 or r.rc == 2) and (anyLineContains(r.out, '[[script] scriptArgs*]') or anyLineContains(r.err, '[scriptfile] [scriptarg...]')):
            print "Got usage error from:"
            print "  " + sps.shellify(command)
            assert i > 0
            jsInteresting.deleteLogs(prefix)
        elif r.lev > jsInteresting.JS_OVERALL_MISMATCH:
            # would be more efficient to run lithium on one or the other, but meh
            print infilename + " | " + jsInteresting.summaryString(r.issues + ["compareJIT found a more serious bug"], r.lev, r.runinfo.elapsedtime)
            with open(logPrefix + "-summary.txt", 'wb') as f:
                f.write('\n'.join(r.issues + [sps.shellify(command), "compareJIT found a more serious bug"]) + '\n')
            print "  " + sps.shellify(command)
            return (r.lev, r.crashInfo)
        elif r.lev != jsInteresting.JS_FINE or r.rc != 0:
            print infilename + " | " + jsInteresting.summaryString(r.issues + ["compareJIT is not comparing output, because the shell exited strangely"], r.lev, r.runinfo.elapsedtime)
            print "  " + sps.shellify(command)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return (jsInteresting.JS_FINE, None)
        elif oom:
            # If the shell or python hit a memory limit, we consider the rest of the computation
            # "tainted" for the purpose of correctness comparison.
            message = "compareJIT is not comparing output: OOM"
            print infilename + " | " + jsInteresting.summaryString(r.issues + [message], r.lev, r.runinfo.elapsedtime)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return (jsInteresting.JS_FINE, None)
        elif i == 0:
            # Stash output from this run (the first one), so for subsequent runs, we can compare against it.
            (r0, prefix0) = (r, prefix)
        else:
            # Compare the output of this run (r.out) to the output of the first run (r0.out), etc.

            def fpuOptionDisabledAsmOnOneSide(fpuAsmMsg):
                fpuOptionDisabledAsm = fpuAsmMsg in r0.err or fpuAsmMsg in r.err
                fpuOptionDiffers = (("--no-fpu" in commands[0]) != ("--no-fpu" in command))
                return fpuOptionDisabledAsm and fpuOptionDiffers

            def optionDisabledAsmOnOneSide():
                asmMsg = "asm.js type error: Disabled by javascript.options.asmjs"
                optionDisabledAsm = anyLineContains(r0.err, asmMsg) or anyLineContains(r.err, asmMsg)
                optionDiffers = (("--no-asmjs" in commands[0]) != ("--no-asmjs" in command))
                return optionDisabledAsm and optionDiffers

            mismatchErr = (r.err != r0.err and
                           # --no-fpu (on debug x86_32 only) turns off asm.js compilation, among other things.
                           # This should only affect asm.js diagnostics on stderr.
                           not fpuOptionDisabledAsmOnOneSide("asm.js type error: Disabled by lack of floating point support") and
                           # And also wasm stuff. See bug 1243031.
                           not fpuOptionDisabledAsmOnOneSide("WebAssembly is not supported on the current device") and
                           not optionDisabledAsmOnOneSide())
            mismatchOut = (r.out != r0.out)

            if mismatchErr or mismatchOut:
                # Generate a short summary for stdout and a long summary for a "*-summary.txt" file.
                rerunCommand = sps.shellify(['~/funfuzz/js/compareJIT.py', "--flags="+' '.join(flags),
                                             "--timeout="+str(options.timeout), options.knownPath, jsEngine,
                                             os.path.basename(infilename)])
                (summary, issues) = summarizeMismatch(mismatchErr, mismatchOut, prefix0, prefix)
                summary = "  " + sps.shellify(commands[0]) + "\n  " + sps.shellify(command) + "\n\n" + summary
                with open(logPrefix + "-summary.txt", 'wb') as f:
                    f.write(rerunCommand + "\n\n" + summary)
                print infilename + " | " + jsInteresting.summaryString(issues, jsInteresting.JS_OVERALL_MISMATCH, r.runinfo.elapsedtime)
                if quickMode:
                    print rerunCommand
                if showDetailedDiffs:
                    print summary
                    print ""
                # Create a crashInfo object with empty stdout, and stderr showing diffs
                pc = ProgramConfiguration.fromBinary(jsEngine)
                pc.addProgramArguments(flags)
                crashInfo = CrashInfo.CrashInfo.fromRawCrashData([], summary, pc)
                return (jsInteresting.JS_OVERALL_MISMATCH, crashInfo)
            else:
                # print "compareJIT: match"
                jsInteresting.deleteLogs(prefix)

    # All matched :)
    jsInteresting.deleteLogs(prefix0)
    return (jsInteresting.JS_FINE, None)
Example #4
0
def compareLevel(jsEngine, flags, infilename, logPrefix, knownPath, timeout, showDetailedDiffs, quickMode):
    combos = shellFlags.basicFlagSets(jsEngine)

    if quickMode:
        # Only used during initial fuzzing. Allowed to have false negatives.
        combos = [combos[0]]

    if len(flags):
        combos.append(flags)

    commands = [[jsEngine] + combo + [infilename] for combo in combos]

    for i in range(0, len(commands)):
        prefix = logPrefix + "-r" + str(i)
        command = commands[i]
        (lev, issues, r) = jsInteresting.baseLevel(command, timeout, knownPath, prefix)

        with open(prefix + "-out.txt") as f:
            r.out = f.read(lengthLimit)
        with open(prefix + "-err.txt") as f:
            r.err = f.read(lengthLimit)

        oom = jsInteresting.hitMemoryLimit(r.err)
        if (not oom) and (len(r.err) + 5 > lengthLimit):
            # The output was too long for Python to read it in all at once. Assume the worst.
            oom = "stderr too long"

        r.err = ignoreSomeOfStderr(r.err)

        if (r.rc == 1 or r.rc == 2) and (r.out.find('[[script] scriptArgs*]') != -1 or r.err.find('[scriptfile] [scriptarg...]') != -1):
            print "Got usage error from:"
            print "  " + sps.shellify(command)
            assert i > 0
            jsInteresting.deleteLogs(prefix)
        elif lev > jsInteresting.JS_OVERALL_MISMATCH:
            # would be more efficient to run lithium on one or the other, but meh
            print infilename + " | " + jsInteresting.summaryString(issues + ["compareJIT found a more serious bug"], lev, r.elapsedtime)
            with open(logPrefix + "-summary.txt", 'wb') as f:
                f.write('\n'.join(issues + [sps.shellify(command), "compareJIT found a more serious bug"]) + '\n')
            print "  " + sps.shellify(command)
            return lev
        elif lev != jsInteresting.JS_FINE:
            print infilename + " | " + jsInteresting.summaryString(issues + ["compareJIT is not comparing output, because the shell exited strangely"], lev, r.elapsedtime)
            print "  " + sps.shellify(command)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return jsInteresting.JS_FINE
        elif oom:
            # If the shell or python hit a memory limit, we consider the rest of the computation
            # "tainted" for the purpose of correctness comparison.
            message = "compareJIT is not comparing output: OOM (" + oom + ")"
            print infilename + " | " + jsInteresting.summaryString(issues + [message], lev, r.elapsedtime)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return jsInteresting.JS_FINE
        elif i == 0:
            # Stash output from this run (the first one), so for subsequent runs, we can compare against it.
            (r0, prefix0) = (r, prefix)
        else:
            # Compare the output of this run (r.out) to the output of the first run (r0.out), etc.

            def fpuOptionDisabledAsmOnOneSide():
                # --no-fpu (on debug x86_32 only) turns off asm.js compilation, among other things.
                # This should only affect asm.js diagnostics on stderr.
                fpuAsmMsg = "asm.js type error: Disabled by lack of floating point support"
                fpuOptionDisabledAsm = fpuAsmMsg in r0.err or fpuAsmMsg in r.err
                fpuOptionDiffers = (("--no-fpu" in commands[0]) != ("--no-fpu" in command))
                return (fpuOptionDisabledAsm and fpuOptionDiffers)

            def optionDisabledAsmOnOneSide():
                asmMsg = "asm.js type error: Disabled by javascript.options.asmjs"
                optionDisabledAsm = asmMsg in r0.err or asmMsg in r.err
                optionDiffers = (("--no-asmjs" in commands[0]) != ("--no-asmjs" in command))
                return (optionDisabledAsm and optionDiffers)

            mismatchErr = (r.err != r0.err and not fpuOptionDisabledAsmOnOneSide() and not optionDisabledAsmOnOneSide())
            mismatchOut = (r.out != r0.out)

            if mismatchErr or mismatchOut:
                # Generate a short summary for stdout and a long summary for a "*-summary.txt" file.
                rerunCommand = sps.shellify(['~/funfuzz/js/compareJIT.py', "--flags="+' '.join(flags),
                                             "--timeout="+str(timeout), knownPath, jsEngine,
                                             os.path.basename(infilename)])
                (summary, issues) = summarizeMismatch(mismatchErr, mismatchOut, prefix0, prefix)
                summary = "  " + sps.shellify(commands[0]) + "\n  " + sps.shellify(command) + "\n\n" + summary
                with open(logPrefix + "-summary.txt", 'wb') as f:
                    f.write(rerunCommand + "\n\n" + summary)
                print infilename + " | " + jsInteresting.summaryString(issues, jsInteresting.JS_OVERALL_MISMATCH, r.elapsedtime)
                if quickMode:
                    print rerunCommand
                if showDetailedDiffs:
                    print summary
                    print ""
                return jsInteresting.JS_OVERALL_MISMATCH
            else:
                #print "compareJIT: match"
                jsInteresting.deleteLogs(prefix)

    # All matched :)
    jsInteresting.deleteLogs(prefix0)
    return jsInteresting.JS_FINE
def compareLevel(jsEngine, flags, infilename, logPrefix, options,
                 showDetailedDiffs, quickMode):
    # options dict must be one we can pass to jsInteresting.ShellResult
    # we also use it directly for knownPath, timeout, and collector
    # Return: (lev, crashInfo) or (jsInteresting.JS_FINE, None)

    combos = shellFlags.basicFlagSets(jsEngine)

    if quickMode:
        # Only used during initial fuzzing. Allowed to have false negatives.
        combos = [combos[0]]

    if len(flags):
        combos.append(flags)

    commands = [[jsEngine] + combo + [infilename] for combo in combos]

    for i in range(0, len(commands)):
        prefix = logPrefix + "-r" + str(i)
        command = commands[i]
        r = jsInteresting.ShellResult(options, command, prefix, True)

        oom = jsInteresting.oomed(r.err)
        r.err = ignoreSomeOfStderr(r.err)

        if (r.rc == 1 or r.rc == 2) and (
                anyLineContains(r.out, '[[script] scriptArgs*]')
                or anyLineContains(r.err, '[scriptfile] [scriptarg...]')):
            print "Got usage error from:"
            print "  " + sps.shellify(command)
            assert i > 0
            jsInteresting.deleteLogs(prefix)
        elif r.lev > jsInteresting.JS_OVERALL_MISMATCH:
            # would be more efficient to run lithium on one or the other, but meh
            print infilename + " | " + jsInteresting.summaryString(
                r.issues + ["compareJIT found a more serious bug"], r.lev,
                r.runinfo.elapsedtime)
            with open(logPrefix + "-summary.txt", 'wb') as f:
                f.write('\n'.join(r.issues + [
                    sps.shellify(command),
                    "compareJIT found a more serious bug"
                ]) + '\n')
            print "  " + sps.shellify(command)
            return (r.lev, r.crashInfo)
        elif r.lev != jsInteresting.JS_FINE or r.rc != 0:
            print infilename + " | " + jsInteresting.summaryString(
                r.issues + [
                    "compareJIT is not comparing output, because the shell exited strangely"
                ], r.lev, r.runinfo.elapsedtime)
            print "  " + sps.shellify(command)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return (jsInteresting.JS_FINE, None)
        elif oom:
            # If the shell or python hit a memory limit, we consider the rest of the computation
            # "tainted" for the purpose of correctness comparison.
            message = "compareJIT is not comparing output: OOM"
            print infilename + " | " + jsInteresting.summaryString(
                r.issues + [message], r.lev, r.runinfo.elapsedtime)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return (jsInteresting.JS_FINE, None)
        elif i == 0:
            # Stash output from this run (the first one), so for subsequent runs, we can compare against it.
            (r0, prefix0) = (r, prefix)
        else:
            # Compare the output of this run (r.out) to the output of the first run (r0.out), etc.

            def fpuOptionDisabledAsmOnOneSide(fpuAsmMsg):
                fpuOptionDisabledAsm = fpuAsmMsg in r0.err or fpuAsmMsg in r.err
                fpuOptionDiffers = (("--no-fpu" in commands[0]) !=
                                    ("--no-fpu" in command))
                return fpuOptionDisabledAsm and fpuOptionDiffers

            def optionDisabledAsmOnOneSide():
                asmMsg = "asm.js type error: Disabled by javascript.options.asmjs"
                optionDisabledAsm = anyLineContains(
                    r0.err, asmMsg) or anyLineContains(r.err, asmMsg)
                optionDiffers = (("--no-asmjs" in commands[0]) !=
                                 ("--no-asmjs" in command))
                return optionDisabledAsm and optionDiffers

            mismatchErr = (
                r.err != r0.err and
                # --no-fpu (on debug x86_32 only) turns off asm.js compilation, among other things.
                # This should only affect asm.js diagnostics on stderr.
                not fpuOptionDisabledAsmOnOneSide(
                    "asm.js type error: Disabled by lack of floating point support"
                ) and
                # And also wasm stuff. See bug 1243031.
                not fpuOptionDisabledAsmOnOneSide(
                    "WebAssembly is not supported on the current device")
                and not optionDisabledAsmOnOneSide())
            mismatchOut = (r.out != r0.out)

            if mismatchErr or mismatchOut:
                # Generate a short summary for stdout and a long summary for a "*-summary.txt" file.
                rerunCommand = sps.shellify([
                    '~/funfuzz/js/compareJIT.py', "--flags=" + ' '.join(flags),
                    "--timeout=" + str(options.timeout), options.knownPath,
                    jsEngine,
                    os.path.basename(infilename)
                ])
                (summary, issues) = summarizeMismatch(mismatchErr, mismatchOut,
                                                      prefix0, prefix)
                summary = "  " + sps.shellify(
                    commands[0]) + "\n  " + sps.shellify(
                        command) + "\n\n" + summary
                with open(logPrefix + "-summary.txt", 'wb') as f:
                    f.write(rerunCommand + "\n\n" + summary)
                print infilename + " | " + jsInteresting.summaryString(
                    issues, jsInteresting.JS_OVERALL_MISMATCH,
                    r.runinfo.elapsedtime)
                if quickMode:
                    print rerunCommand
                if showDetailedDiffs:
                    print summary
                    print ""
                # Create a crashInfo object with empty stdout, and stderr showing diffs
                pc = ProgramConfiguration.fromBinary(jsEngine)
                pc.addProgramArguments(flags)
                crashInfo = CrashInfo.CrashInfo.fromRawCrashData([], summary,
                                                                 pc)
                return (jsInteresting.JS_OVERALL_MISMATCH, crashInfo)
            else:
                # print "compareJIT: match"
                jsInteresting.deleteLogs(prefix)

    # All matched :)
    jsInteresting.deleteLogs(prefix0)
    return (jsInteresting.JS_FINE, None)
Example #6
0
def many_timed_runs(targetTime, wtmpDir, args):
    options = parseOpts(args)
    engineFlags = options.engineFlags  # engineFlags is overwritten later if --random-flags is set.
    startTime = time.time()

    if os.path.isdir(sps.normExpUserPath(options.repo)):
        regressionTestListFile = sps.normExpUserPath(os.path.join(wtmpDir, "regression-tests.list"))
        with open(regressionTestListFile, "wb") as f:
            for fn in inTreeRegressionTests(options.repo):
                f.write(fn + "\n")
        regressionTestPrologue = makeRegressionTestPrologue(options.repo, regressionTestListFile)
    else:
        regressionTestPrologue = ""

    fuzzjs = sps.normExpUserPath(os.path.join(wtmpDir, "jsfunfuzz.js"))
    linkFuzzer(fuzzjs, options.repo, regressionTestPrologue)

    iteration = 0
    while True:
        if targetTime and time.time() > startTime + targetTime:
            print "Out of time!"
            os.remove(fuzzjs)
            if len(os.listdir(wtmpDir)) == 0:
                os.rmdir(wtmpDir)
            return (lithOps.HAPPY, None)

        # Construct command needed to loop jsfunfuzz fuzzing.
        jsInterestingArgs = []
        jsInterestingArgs.append('--timeout=' + str(options.timeout))
        if options.valgrind:
            jsInterestingArgs.append('--valgrind')
        jsInterestingArgs.append(options.knownPath)
        jsInterestingArgs.append(options.jsEngine)
        if options.randomFlags:
            engineFlags = shellFlags.randomFlagSet(options.jsEngine)
            jsInterestingArgs.extend(engineFlags)
        jsInterestingArgs.extend(['-e', 'maxRunTime=' + str(options.timeout*(1000/2))])
        jsInterestingArgs.extend(['-f', fuzzjs])
        jsunhappyOptions = jsInteresting.parseOptions(jsInterestingArgs)

        iteration += 1
        logPrefix = sps.normExpUserPath(os.path.join(wtmpDir, "w" + str(iteration)))

        level = jsInteresting.jsfunfuzzLevel(jsunhappyOptions, logPrefix)

        if level != jsInteresting.JS_FINE:
            showtail(logPrefix + "-out.txt")
            showtail(logPrefix + "-err.txt")

            # splice jsfunfuzz.js with `grep FRC wN-out`
            filenameToReduce = logPrefix + "-reduced.js"
            [before, after] = fileManipulation.fuzzSplice(fuzzjs)

            with open(logPrefix + '-out.txt', 'rb') as f:
                newfileLines = before + [l.replace('/*FRC*/', '') for l in fileManipulation.linesStartingWith(f, "/*FRC*/")] + after
            fileManipulation.writeLinesToFile(newfileLines, logPrefix + "-orig.js")
            fileManipulation.writeLinesToFile(newfileLines, filenameToReduce)

            # Run Lithium and autobisect (make a reduced testcase and find a regression window)
            itest = [interestingpy]
            if options.valgrind:
                itest.append("--valgrind")
            itest.append("--minlevel=" + str(level))
            itest.append("--timeout=" + str(options.timeout))
            itest.append(options.knownPath)
            (lithResult, lithDetails) = pinpoint.pinpoint(itest, logPrefix, options.jsEngine, engineFlags, filenameToReduce,
                                                          options.repo, options.buildOptionsStr, targetTime, level)
            if targetTime:
                return (lithResult, lithDetails)

        else:
            shellIsDeterministic = inspectShell.queryBuildConfiguration(options.jsEngine, 'more-deterministic')
            flagsAreDeterministic = "--dump-bytecode" not in engineFlags and '-D' not in engineFlags
            if options.useCompareJIT and level == jsInteresting.JS_FINE and \
                    shellIsDeterministic and flagsAreDeterministic:
                linesToCompare = jitCompareLines(logPrefix + '-out.txt', "/*FCM*/")
                jitcomparefilename = logPrefix + "-cj-in.js"
                fileManipulation.writeLinesToFile(linesToCompare, jitcomparefilename)
                (lithResult, lithDetails) = compareJIT.compareJIT(options.jsEngine, engineFlags, jitcomparefilename,
                                                                  logPrefix + "-cj", options.knownPath, options.repo,
                                                                  options.buildOptionsStr, options.timeout, targetTime)
                if lithResult == lithOps.HAPPY:
                    os.remove(jitcomparefilename)
                if targetTime and lithResult != lithOps.HAPPY:
                    jsInteresting.deleteLogs(logPrefix)
                    return (lithResult, lithDetails)
            jsInteresting.deleteLogs(logPrefix)
Example #7
0
def compareLevel(jsEngine, flags, infilename, logPrefix, knownPath, timeout,
                 showDetailedDiffs, quickMode):
    combos = shellFlags.basicFlagSets(jsEngine)

    if quickMode:
        # Only used during initial fuzzing. Allowed to have false negatives.
        combos = [combos[0]]

    if len(flags):
        combos.append(flags)

    commands = [[jsEngine] + combo + [infilename] for combo in combos]

    for i in range(0, len(commands)):
        prefix = logPrefix + "-r" + str(i)
        command = commands[i]
        (lev, issues, r) = jsInteresting.baseLevel(command, timeout, knownPath,
                                                   prefix)

        with open(prefix + "-out.txt") as f:
            r.out = f.read(lengthLimit)
        with open(prefix + "-err.txt") as f:
            r.err = f.read(lengthLimit)

        oom = jsInteresting.hitMemoryLimit(r.err)
        if (not oom) and (len(r.err) + 5 > lengthLimit):
            # The output was too long for Python to read it in all at once. Assume the worst.
            oom = "stderr too long"

        r.err = ignoreSomeOfStderr(r.err)

        if (r.rc == 1 or r.rc
                == 2) and (r.out.find('[[script] scriptArgs*]') != -1
                           or r.err.find('[scriptfile] [scriptarg...]') != -1):
            print "Got usage error from:"
            print "  " + sps.shellify(command)
            assert i > 0
            jsInteresting.deleteLogs(prefix)
        elif lev > jsInteresting.JS_OVERALL_MISMATCH:
            # would be more efficient to run lithium on one or the other, but meh
            print infilename + " | " + jsInteresting.summaryString(
                issues + ["compareJIT found a more serious bug"], lev,
                r.elapsedtime)
            with open(logPrefix + "-summary.txt", 'wb') as f:
                f.write('\n'.join(issues + [
                    sps.shellify(command),
                    "compareJIT found a more serious bug"
                ]) + '\n')
            print "  " + sps.shellify(command)
            return lev
        elif lev != jsInteresting.JS_FINE:
            print infilename + " | " + jsInteresting.summaryString(
                issues + [
                    "compareJIT is not comparing output, because the shell exited strangely"
                ], lev, r.elapsedtime)
            print "  " + sps.shellify(command)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return jsInteresting.JS_FINE
        elif oom:
            # If the shell or python hit a memory limit, we consider the rest of the computation
            # "tainted" for the purpose of correctness comparison.
            message = "compareJIT is not comparing output: OOM (" + oom + ")"
            print infilename + " | " + jsInteresting.summaryString(
                issues + [message], lev, r.elapsedtime)
            jsInteresting.deleteLogs(prefix)
            if i == 0:
                return jsInteresting.JS_FINE
        elif i == 0:
            # Stash output from this run (the first one), so for subsequent runs, we can compare against it.
            (r0, prefix0) = (r, prefix)
        else:
            # Compare the output of this run (r.out) to the output of the first run (r0.out), etc.

            def fpuOptionDisabledAsmOnOneSide():
                # --no-fpu (on debug x86_32 only) turns off asm.js compilation, among other things.
                # This should only affect asm.js diagnostics on stderr.
                fpuAsmMsg = "asm.js type error: Disabled by lack of floating point support"
                fpuOptionDisabledAsm = fpuAsmMsg in r0.err or fpuAsmMsg in r.err
                fpuOptionDiffers = (("--no-fpu" in commands[0]) !=
                                    ("--no-fpu" in command))
                return (fpuOptionDisabledAsm and fpuOptionDiffers)

            def optionDisabledAsmOnOneSide():
                asmMsg = "asm.js type error: Disabled by javascript.options.asmjs"
                optionDisabledAsm = asmMsg in r0.err or asmMsg in r.err
                optionDiffers = (("--no-asmjs" in commands[0]) !=
                                 ("--no-asmjs" in command))
                return (optionDisabledAsm and optionDiffers)

            mismatchErr = (r.err != r0.err
                           and not fpuOptionDisabledAsmOnOneSide()
                           and not optionDisabledAsmOnOneSide())
            mismatchOut = (r.out != r0.out)

            if mismatchErr or mismatchOut:
                # Generate a short summary for stdout and a long summary for a "*-summary.txt" file.
                rerunCommand = sps.shellify([
                    '~/funfuzz/js/compareJIT.py', "--flags=" + ' '.join(flags),
                    "--timeout=" + str(timeout), knownPath, jsEngine,
                    os.path.basename(infilename)
                ])
                (summary, issues) = summarizeMismatch(mismatchErr, mismatchOut,
                                                      prefix0, prefix)
                summary = "  " + sps.shellify(
                    commands[0]) + "\n  " + sps.shellify(
                        command) + "\n\n" + summary
                with open(logPrefix + "-summary.txt", 'wb') as f:
                    f.write(rerunCommand + "\n\n" + summary)
                print infilename + " | " + jsInteresting.summaryString(
                    issues, jsInteresting.JS_OVERALL_MISMATCH, r.elapsedtime)
                if quickMode:
                    print rerunCommand
                if showDetailedDiffs:
                    print summary
                    print ""
                return jsInteresting.JS_OVERALL_MISMATCH
            else:
                #print "compareJIT: match"
                jsInteresting.deleteLogs(prefix)

    # All matched :)
    jsInteresting.deleteLogs(prefix0)
    return jsInteresting.JS_FINE