Example #1
0
def test_parse_args(capsys, tmp_path):
    "test that grizzly.reduce args are accepted and validated"
    exe = tmp_path / "binary"
    inp = tmp_path / "input"

    # missing arg tests
    with pytest.raises(SystemExit):
        ReducerArgs().parse_args([])
    _, err = capsys.readouterr()
    with pytest.raises(SystemExit):
        ReducerArgs().parse_args([str(exe)])
    _, err = capsys.readouterr()

    # invalid binary tests
    with pytest.raises(SystemExit):
        ReducerArgs().parse_args([str(exe), str(inp)])
    _, err = capsys.readouterr()
    assert "error: file not found: %r" % (str(exe),) in err
    exe.mkdir()
    with pytest.raises(SystemExit):
        ReducerArgs().parse_args([str(exe), str(inp)])
    _, err = capsys.readouterr()
    assert "error: file not found: %r" % (str(exe),) in err
    exe.rmdir()
    exe.touch()

    # invalid input tests
    with pytest.raises(SystemExit):
        ReducerArgs().parse_args([str(exe), str(inp)])
    _, err = capsys.readouterr()
    assert "error: %r does not exist" % (str(inp),) in err
    inp.touch()
    with pytest.raises(SystemExit):
        ReducerArgs().parse_args([str(exe), str(inp)])
    _, err = capsys.readouterr()
    assert "error: Testcase should be a folder, zip, or html file" in err
    inp.unlink()
    with pytest.raises(SystemExit):
        ReducerFuzzManagerIDArgs().parse_args([str(exe), str(inp)])
    _, err = capsys.readouterr()
    assert "invalid int value" in err

    # valid binary & inputs
    (tmp_path / "input.zip").touch()
    zipf = tmp_path / "input.zip"
    ReducerArgs().parse_args([str(exe), str(zipf)])
    zipf.unlink()
    inp.mkdir()
    (inp / "test_info.txt").touch()
    ReducerArgs().parse_args([str(exe), str(inp)])
    ReducerFuzzManagerIDArgs().parse_args([str(exe), '123'])

    # sig/environ tests
    fname = tmp_path / "file.txt"
    for arg in ("--sig", "--environ"):
        with pytest.raises(SystemExit):
            ReducerArgs().parse_args([str(exe), str(inp), arg, str(fname)])
        _, err = capsys.readouterr()
        assert "error: file not found: %r" % (str(fname),) in err
        fname.mkdir()
        with pytest.raises(SystemExit):
            ReducerArgs().parse_args([str(exe), str(inp), arg, str(fname)])
        _, err = capsys.readouterr()
        assert "error: file not found: %r" % (str(fname),) in err
        fname.rmdir()
        fname.touch()
        ReducerArgs().parse_args([str(exe), str(inp), arg, str(fname)])
        fname.unlink()

    # repeat/min-crashes tests
    for arg in ("--repeat", "--min-crashes"):
        with pytest.raises(SystemExit):
            ReducerArgs().parse_args([str(exe), str(inp), arg, "abc"])
        with pytest.raises(SystemExit):
            ReducerArgs().parse_args([str(exe), str(inp), arg, "-1"])
        _, err = capsys.readouterr()
        assert "'%s' value must be positive" % (arg,) in err
        with pytest.raises(SystemExit):
            ReducerArgs().parse_args([str(exe), str(inp), arg, "0"])
        _, err = capsys.readouterr()
        assert "'%s' value must be positive" % (arg,) in err
        ReducerArgs().parse_args([str(exe), str(inp), arg, "1"])
        ReducerArgs().parse_args([str(exe), str(inp), arg, "10"])
Example #2
0
def test_crash_main_no_repro_specific(job, monkeypatch, tmp_path):  # noqa pylint: disable=redefined-outer-name
    "crash.main --fuzzmanager updates quality"
    expect_patch = [reporter.FuzzManagerReporter.QUAL_NOT_REPRODUCIBLE]

    class ReporterNoSubmit(reporter.FuzzManagerReporter):
        (tmp_path / ".fuzzmanagerconf").touch()
        FM_CONFIG = str(tmp_path / ".fuzzmanagerconf")

        def _reset(self):
            pass

        def _submit(self, *_args, **_kwds):
            # make sure _submit() is not called
            assert False

    class FakeCollector(object):
        serverProtocol = 'https'
        serverHost = 'mozilla.org'
        serverPort = 8000

        def get(self, _url, **kwds):

            class response(object):

                class headers(object):

                    @staticmethod
                    def get(value, default):
                        assert value.lower() == 'content-disposition'
                        return 'attachment; filename="test.zip"'

                @staticmethod
                def json():
                    return {
                        'testcase_quality': reporter.FuzzManagerReporter.QUAL_REQUEST_SPECIFIC,
                        'tool': 'test-tool'}
                content = (inp / "test.zip").read_bytes()
            return response

        def patch(self, _url, **kwds):
            data = kwds["data"]
            assert set(data.keys()) == {"testcase_quality"}
            assert expect_patch
            assert data["testcase_quality"] == expect_patch.pop(0)

    # uses the job fixture from test_reduce which reduces testcases to the string "required\n"
    monkeypatch.setattr(reduce, "ReductionJob", lambda *a, **kw: job)
    monkeypatch.setattr(reporter, "Collector", FakeCollector)
    monkeypatch.setattr(reduce, "FuzzManagerReporter", ReporterNoSubmit)
    monkeypatch.setattr(crash, "Collector", FakeCollector)

    (tmp_path / "binary").touch()
    exe = tmp_path / "binary"
    (tmp_path / "binary.fuzzmanagerconf").write_text(
        "[Main]\n"
        "platform = x86-64\n"
        "product = mozilla-central\n"
        "os = linux\n"
    )
    (tmp_path / "input").mkdir()
    inp = tmp_path / "input"
    (inp / "test_info.txt").write_text("landing page: test.html")
    (inp / "test.html").write_text("fluff\n")
    with zipfile.ZipFile(str(inp / "test.zip"), "w") as zip_fp:
        zip_fp.write(str(inp / "test_info.txt"), "test_info.txt")
        zip_fp.write(str(inp / "test.html"), "test.html")
    args = ReducerFuzzManagerIDArgs().parse_args([str(exe), '1234', '--fuzzmanager'])
    assert crash.main(args) == 1
    assert not expect_patch
Example #3
0
def test_crash_main_repro(monkeypatch, tmp_path):  # noqa pylint: disable=redefined-outer-name
    "crash.main --fuzzmanager updates quality"
    # expect Collector.patch to be called with these qualities
    expect_patch = [
        reporter.FuzzManagerReporter.QUAL_REPRODUCIBLE,
        reporter.FuzzManagerReporter.QUAL_REDUCED_ORIGINAL
    ]
    submitted = [False]

    class ReporterNoSubmit(reporter.FuzzManagerReporter):
        (tmp_path / ".fuzzmanagerconf").touch()
        FM_CONFIG = str(tmp_path / ".fuzzmanagerconf")

        def _submit_report(self, *_args, **_kwds):
            # check that the crash was already marked reproducible, but not yet marked reduced
            assert expect_patch == [
                reporter.FuzzManagerReporter.QUAL_REDUCED_ORIGINAL
            ]
            submitted[0] = True

    class FakeCollector(object):
        serverProtocol = 'https'
        serverHost = 'mozilla.org'
        serverPort = 8000

        def get(self, _url, **kwds):
            class response(object):
                class headers(object):
                    @staticmethod
                    def get(value, default):
                        assert value.lower() == 'content-disposition'
                        return 'attachment; filename="test.zip"'

                @staticmethod
                def json():
                    return {
                        'testcase_quality':
                        reporter.FuzzManagerReporter.QUAL_UNREDUCED,
                        'tool': 'test-tool'
                    }

                content = (inp / "test.zip").read_bytes()

            return response

        def patch(self, _url, **kwds):
            data = kwds["data"]
            assert set(data.keys()) == {"testcase_quality"}
            assert expect_patch
            assert data["testcase_quality"] == expect_patch.pop(0)

    monkeypatch.setattr(reporter, "Collector", FakeCollector)
    monkeypatch.setattr(reduce, "FuzzManagerReporter", ReporterNoSubmit)
    monkeypatch.setattr(crash, "Collector", FakeCollector)

    (tmp_path / "binary").touch()
    exe = tmp_path / "binary"
    (tmp_path / "binary.fuzzmanagerconf").write_text(
        "[Main]\n"
        "platform = x86-64\n"
        "product = mozilla-central\n"
        "os = linux\n")
    (tmp_path / "input").mkdir()
    inp = tmp_path / "input"
    (inp / "test_info.txt").write_text("landing page: test.html")
    (inp / "test.html").write_text("fluff\nrequired\n")
    with zipfile.ZipFile(str(inp / "test.zip"), "w") as zip_fp:
        zip_fp.write(str(inp / "test_info.txt"), "test_info.txt")
        zip_fp.write(str(inp / "test.html"), "test.html")
    args = ReducerFuzzManagerIDArgs().parse_args(
        [str(exe), '1234', '--fuzzmanager'])
    assert TestMainCrashReductionJob.main(args) == 0
    assert not expect_patch
    assert submitted[0]