def test_SignatureMatchAssertionSlashes():
    # test that a forward slash assertion signature matches a backwards slash crash, but only on windows
    cfg_linux = ProgramConfiguration('test', 'x86-64', 'linux')
    cfg_windows = ProgramConfiguration('test', 'x86-64', 'windows')

    fs_lines = testAssertionPathFwSlashes.splitlines()
    bs_lines = testAssertionPathBwSlashes.splitlines()

    # native paths on linux use forward slash
    fs_linux = CrashInfo.fromRawCrashData([], [], cfg_linux, auxCrashData=fs_lines)
    # backward slash path on linux -- this is invalid and should never happen
    bs_linux = CrashInfo.fromRawCrashData([], [], cfg_linux, auxCrashData=bs_lines)
    # forward slashes on windows are valid, and this does happen
    fs_windows = CrashInfo.fromRawCrashData([], [], cfg_windows, auxCrashData=fs_lines)
    # native paths on windows use backslash
    bs_windows = CrashInfo.fromRawCrashData([], [], cfg_windows, auxCrashData=bs_lines)

    # test that signature generated from linux assertion matches both
    linux_sig = fs_linux.createCrashSignature()
    assert linux_sig.matches(fs_linux)
    assert not linux_sig.matches(bs_linux)  # this is invalid and should not match
    assert linux_sig.matches(fs_windows)
    assert linux_sig.matches(bs_windows)

    # test that signature generated from windows assertion matches both
    windows_sig = bs_windows.createCrashSignature()
    assert windows_sig.matches(fs_linux)
    assert not windows_sig.matches(bs_linux)  # this is invalid and should not match
    assert windows_sig.matches(fs_windows)
    assert windows_sig.matches(bs_windows)
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "linux")
        crashInfo = CrashInfo.fromRawCrashData(
            [], [], config, auxCrashData=tsanSimpleRaceReport.splitlines())
        testSignature = crashInfo.createCrashSignature()

        self.assertTrue(testSignature.matches(crashInfo))

        outputSymptoms = []

        for symptom in testSignature.symptoms:
            if isinstance(symptom, OutputSymptom):
                self.assertEqual(symptom.src, "crashdata")
                outputSymptoms.append(symptom)

        self.assertEqual(len(outputSymptoms), 3)

        for stringMatchVal in [
                "WARNING: ThreadSanitizer: data race",
                "Write of size 4 at 0x[0-9a-fA-F]+ by thread T1:",
                "Previous read of size 4 at 0x[0-9a-fA-F]+ by main thread:"
        ]:
            found = False
            for symptom in outputSymptoms:
                if symptom.output.value == stringMatchVal:
                    found = True
            self.assertTrue(found,
                            msg="Couldn't find OutputSymptom with value '%s'" %
                            stringMatchVal)
Exemple #3
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "linux")

        crashSignature1 = '{ "symptoms" : [ { "type" : "stackSize", "size" : 8 } ] }'
        crashSignature1Neg = '{ "symptoms" : [ { "type" : "stackSize", "size" : 9 } ] }'

        crashSignature2 = '{ "symptoms" : [ { "type" : "stackSize", "size" : "< 10" } ] }'
        crashSignature2Neg = '{ "symptoms" : [ { "type" : "stackSize", "size" : "> 10" } ] }'

        stackSizeSig1 = CrashSignature(crashSignature1)
        stackSizeSig1Neg = CrashSignature(crashSignature1Neg)

        stackSizeSig2 = CrashSignature(crashSignature2)
        stackSizeSig2Neg = CrashSignature(crashSignature2Neg)

        crashInfo1 = CrashInfo.fromRawCrashData(
            [], [], config, auxCrashData=gdbSampleTrace1.splitlines())

        self.assertIsInstance(crashInfo1, GDBCrashInfo)

        self.assert_(stackSizeSig1.matches(crashInfo1))
        self.assertFalse(stackSizeSig1Neg.matches(crashInfo1))

        self.assert_(stackSizeSig2.matches(crashInfo1))
        self.assertFalse(stackSizeSig2Neg.matches(crashInfo1))
Exemple #4
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "linux")

        crashSignature1 = '{ "symptoms" : [ { "type" : "stackFrame", "functionName" : "internalAppend" } ] }'
        crashSignature1Neg = '{ "symptoms" : [ { "type" : "stackFrame", "functionName" : "foobar" } ] }'

        crashSignature2 = '{ "symptoms" : [ { "type" : "stackFrame", "functionName" : "js::ion::MBasicBlock::setBackedge", "frameNumber" : "<= 4" } ] }'
        crashSignature2Neg = '{ "symptoms" : [ { "type" : "stackFrame", "functionName" : "js::ion::MBasicBlock::setBackedge", "frameNumber" : "> 4" } ] }'

        stackFrameSig1 = CrashSignature(crashSignature1)
        stackFrameSig1Neg = CrashSignature(crashSignature1Neg)

        stackFrameSig2 = CrashSignature(crashSignature2)
        stackFrameSig2Neg = CrashSignature(crashSignature2Neg)

        crashInfo1 = CrashInfo.fromRawCrashData(
            [], [], config, auxCrashData=gdbSampleTrace1.splitlines())

        self.assertIsInstance(crashInfo1, GDBCrashInfo)

        self.assert_(stackFrameSig1.matches(crashInfo1))
        self.assertFalse(stackFrameSig1Neg.matches(crashInfo1))

        self.assert_(stackFrameSig2.matches(crashInfo1))
        self.assertFalse(stackFrameSig2Neg.matches(crashInfo1))
Exemple #5
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86", "linux")
        
        crashInfo1 = GDBCrashInfo([], gdbRegressionTrace1.splitlines(), config)

        self.assertEqual(crashInfo1.backtrace[0], "js::ScriptedIndirectProxyHandler::defineProperty")
        self.assertEqual(crashInfo1.backtrace[1], "js::SetPropertyIgnoringNamedGetter")
def test_SignatureTestCaseMatchTest():
    config = ProgramConfiguration("test", "x86", "linux")

    crashInfo = CrashInfo.fromRawCrashData(
        [], [], config, auxCrashData=testTrace1.splitlines())

    testSig3 = CrashSignature(testSignature3)
    testSig4 = CrashSignature(testSignature4)
    testSig5 = CrashSignature(testSignature5)
    testSig6 = CrashSignature(testSignature6)

    assert not testSig3.matchRequiresTest()
    assert testSig4.matchRequiresTest()
    assert testSig5.matchRequiresTest()

    # Must not match without testcase provided
    assert not testSig4.matches(crashInfo)
    assert not testSig5.matches(crashInfo)
    assert not testSig6.matches(crashInfo)

    # Attach testcase
    crashInfo.testcase = testCase1

    # Must match with testcase provided
    assert testSig4.matches(crashInfo)
    assert testSig5.matches(crashInfo)

    # This one does not match at all
    assert not testSig6.matches(crashInfo)
def test_SignatureCreateTest():
    config = ProgramConfiguration("test", "x86", "linux")

    crashInfo = CrashInfo.fromRawCrashData(
        [], [], config, auxCrashData=testTrace1.splitlines())
    crashSig1 = crashInfo.createCrashSignature(forceCrashAddress=True,
                                               maxFrames=4,
                                               minimumSupportedVersion=10)
    crashSig2 = crashInfo.createCrashSignature(forceCrashAddress=False,
                                               maxFrames=3,
                                               minimumSupportedVersion=10)
    crashSig3 = crashInfo.createCrashSignature(forceCrashInstruction=True,
                                               maxFrames=2,
                                               minimumSupportedVersion=10)

    # Check that all generated signatures match their originating crashInfo
    assert crashSig1.matches(crashInfo)
    assert crashSig2.matches(crashInfo)
    assert crashSig3.matches(crashInfo)

    # Check that the generated signatures look as expected
    assert json.loads(str(crashSig1)) == json.loads(testSignature1)
    assert json.loads(str(crashSig2)) == json.loads(testSignature2)

    #  The third crashInfo misses 2 frames from the top 4 frames, so it will
    #  also include the crash address, even though we did not request it.
    assert json.loads(str(crashSig3)) == json.loads(testSignature3)
def test_SignatureGenerationTSanRaceTest():
    config = ProgramConfiguration("test", "x86-64", "linux")
    with open(os.path.join(CWD, 'resources', 'tsan-simple-race-report.txt'),
              'r') as f:
        crashInfo = CrashInfo.fromRawCrashData(
            [], [], config, auxCrashData=f.read().splitlines())
    testSignature = crashInfo.createCrashSignature()

    assert testSignature.matches(crashInfo)

    outputSymptoms = []

    for symptom in testSignature.symptoms:
        if isinstance(symptom, OutputSymptom):
            assert symptom.src == "crashdata"
            outputSymptoms.append(symptom)

    assert len(outputSymptoms) == 3

    for stringMatchVal in [
            "WARNING: ThreadSanitizer: data race",
            "Write of size 4 at 0x[0-9a-fA-F]+ by thread T1:",
            "Previous read of size 4 at 0x[0-9a-fA-F]+ by main thread:"
    ]:
        found = False
        for symptom in outputSymptoms:
            if symptom.output.value == stringMatchVal:
                found = True
        assert found, "Couldn't find OutputSymptom with value '%s'" % stringMatchVal
def test_SignatureMatchWithUnicode():
    config = ProgramConfiguration('test', 'x86-64', 'linux')
    crashInfo = CrashInfo.fromRawCrashData(
        ["(«f => (generator.throw(f))», «undefined»)"], [], config)
    testSignature = CrashSignature(
        '{"symptoms": [{"src": "stdout", "type": "output", "value": "x"}]}')
    assert not testSignature.matches(crashInfo)
Exemple #10
0
def test_SignatureGenerationTSanRaceTestAtomic():
    config = ProgramConfiguration("test", "x86-64", "linux")
    for fn in ['tsan-report-atomic.txt', 'tsan-report-atomic-swapped.txt']:
        with open(os.path.join(CWD, 'resources', fn), 'r') as f:
            crashInfo = CrashInfo.fromRawCrashData([], [], config, auxCrashData=f.read().splitlines())

        assert(crashInfo.backtrace[0] == "pthread_mutex_destroy")
        assert(crashInfo.createShortSignature() ==
               "ThreadSanitizer: data race [@ pthread_mutex_destroy] vs. [@ pthread_mutex_unlock]")

        testSignature = crashInfo.createCrashSignature()

        assert testSignature.matches(crashInfo)

        outputSymptoms = []

        for symptom in testSignature.symptoms:
            if isinstance(symptom, OutputSymptom):
                assert symptom.src == "crashdata"
                outputSymptoms.append(symptom)

        assert len(outputSymptoms) == 3

        for stringMatchVal in [
            "WARNING: ThreadSanitizer: data race",
            "(Previous )?[Aa]tomic [Rr]ead of size 1 at 0x[0-9a-fA-F]+ by thread T[0-9]+( .+mutexes: .+)?:",
            "(Previous )?[Ww]rite of size 1 at 0x[0-9a-fA-F]+ by main thread( .+mutexes: .+)?:"
        ]:
            found = False
            for symptom in outputSymptoms:
                if symptom.output.value == stringMatchVal:
                    found = True
            assert found, "Couldn't find OutputSymptom with value '%s'" % stringMatchVal
Exemple #11
0
    def getCrashInfo(self,
                     attachTestcase=False,
                     requiredOutputSources=("stdout", "stderr", "crashdata")):
        # TODO: This should be cached at some level
        # TODO: Need to include environment and program arguments here
        configuration = ProgramConfiguration(self.product.name,
                                             self.platform.name, self.os.name,
                                             self.product.version)

        cachedCrashInfo = None
        if self.cachedCrashInfo:
            cachedCrashInfo = json.loads(self.cachedCrashInfo)

        # We can skip loading raw output fields from the database iff
        #   1) we know we don't need them for matching *and*
        #   2) we already have the crash data cached
        (rawStdout, rawStderr, rawCrashData) = (None, None, None)
        if cachedCrashInfo is None or "stdout" in requiredOutputSources:
            rawStdout = self.rawStdout
        if cachedCrashInfo is None or "stderr" in requiredOutputSources:
            rawStderr = self.rawStderr
        if cachedCrashInfo is None or "crashdata" in requiredOutputSources:
            rawCrashData = self.rawCrashData

        crashInfo = CrashInfo.fromRawCrashData(rawStdout,
                                               rawStderr,
                                               configuration,
                                               rawCrashData,
                                               cacheObject=cachedCrashInfo)

        if attachTestcase and self.testcase is not None and not self.testcase.isBinary:
            self.testcase.loadTest()
            crashInfo.testcase = self.testcase.content

        return crashInfo
Exemple #12
0
 def runTest(self):
     config = ProgramConfiguration("test", "x86", "linux")
     
     with open('minidump-example.txt', 'r') as f:
         crashData = f.read().splitlines()
     
     crashInfo = CrashInfo.fromRawCrashData([], [], config, crashData)
     self.assertEqual(crashInfo.crashAddress, long(0x3e800006acb))
Exemple #13
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86", "linux")

        crashInfo1 = CrashInfo.fromRawCrashData([], [], config, auxCrashData=asanTraceCrash.splitlines())
        crashInfo2 = CrashInfo.fromRawCrashData([], asanTraceUAF.splitlines(), config)
        
        self.assertIsInstance(crashInfo1, ASanCrashInfo)
        self.assertIsInstance(crashInfo2, ASanCrashInfo)
Exemple #14
0
def test_SignatureAsanStackOverflowTest():
    config = ProgramConfiguration("test", "x86-64", "linux")
    crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testAsanStackOverflow.splitlines())

    testSig = crashInfoPos.createCrashSignature()

    # Check matches appropriately
    assert testSig.matches(crashInfoPos)
Exemple #15
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "macosx")

        with open('apple-crash-report-example.txt', 'r') as f:
            crashData = f.read().splitlines()

        crashInfo = CrashInfo.fromRawCrashData([], [], config, crashData)
        self.assertEqual(crashInfo.crashAddress, long(0x00007fff5f3fff98))
Exemple #16
0
def test_SignatureAsanFailedAllocTest():
    config = ProgramConfiguration("test", "x86-64", "linux")
    crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testAsanFailedAlloc.splitlines())

    testSig = crashInfoPos.createCrashSignature()
    assert "/AddressSanitizer failed to allocate" in str(testSig)
    assert testSig.matches(crashInfoPos)
    assert isinstance(testSig.symptoms[1], StackFramesSymptom)
 def runTest(self):
     config = ProgramConfiguration('test', 'x86-64', 'linux')
     crashInfo = CrashInfo.fromRawCrashData(
         ["(«f => (generator.throw(f))», «undefined»)"], [], config)
     testSignature = CrashSignature(
         '{"symptoms": [{"src": "stdout", "type": "output", "value": "x"}]}'
     )
     self.assertFalse(testSignature.matches(crashInfo))
Exemple #18
0
def test_SignatureStackSizeTest():
    config = ProgramConfiguration("test", "x86-64", "linux")
    crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testAsanLongTrace.splitlines())

    # The test signature uses > 15 which was previously interpreted as 0x15
    # while the test crash data has 16 frames.
    testSig = CrashSignature(testSignatureStackSize)
    assert testSig.matches(crashInfoPos)
Exemple #19
0
 def runTest(self):
     config = ProgramConfiguration("test", "x86", "linux")
     
     crashInfo = CrashInfo.fromRawCrashData([], [], config, ubsanSampleTrace1.splitlines())
     self.assertEqual(crashInfo.backtrace[0], "WelsDec::BsGetUe")
     self.assertEqual(crashInfo.backtrace[9], "_start")
     
     self.assertEqual(crashInfo.backtrace[11], "Lex< >")
Exemple #20
0
    def create(self, attrs):
        '''
        Create a CrashEntry instance based on the given dictionary of values
        received. We need to unflatten foreign relationships like product,
        platform, os and client and create the foreign objects on the fly
        if they don't exist in our database yet.
        '''
        missing_keys = {'rawStdout', 'rawStderr', 'rawCrashData'} - set(attrs.keys())
        if missing_keys:
            raise InvalidArgumentException({key: ["This field is required."] for key in missing_keys})

        attrs['product'] = Product.objects.get_or_create(**attrs['product'])[0]
        attrs['platform'] = Platform.objects.get_or_create(**attrs['platform'])[0]
        attrs['os'] = OS.objects.get_or_create(**attrs['os'])[0]
        attrs['client'] = Client.objects.get_or_create(**attrs['client'])[0]
        attrs['tool'] = Tool.objects.get_or_create(**attrs['tool'])[0]

        # Parse the incoming data using the crash signature package from FTB
        configuration = ProgramConfiguration(attrs['product'].name, attrs['platform'].name, attrs['os'].name,
                                             attrs['product'].version)
        crashInfo = CrashInfo.fromRawCrashData(attrs['rawStdout'], attrs['rawStderr'], configuration,
                                               attrs['rawCrashData'])

        # Populate certain fields here from the CrashInfo object we just got
        if crashInfo.crashAddress is not None:
            attrs['crashAddress'] = hex(crashInfo.crashAddress)
        attrs['shortSignature'] = crashInfo.createShortSignature()

        # If a testcase is supplied, create a testcase object and store it
        if 'test' in attrs['testcase']:

            testcase = attrs['testcase']
            testcase_ext = attrs.pop('testcase_ext', None)
            testcase_quality = testcase.get('quality', 0)
            testcase_isbinary = testcase.get('isBinary', False)
            testcase = testcase['test']

            if testcase_ext is None:
                raise RuntimeError("Must provide testcase extension when providing testcase")

            if testcase_isbinary:
                testcase = base64.b64decode(testcase)

            h = hashlib.new('sha1')
            if testcase_isbinary:
                h.update(str(testcase))
            else:
                h.update(repr(testcase))

            dbobj = TestCase(quality=testcase_quality, isBinary=testcase_isbinary, size=len(testcase))
            dbobj.test.save("%s.%s" % (h.hexdigest(), testcase_ext), ContentFile(testcase))
            dbobj.save()
            attrs['testcase'] = dbobj
        else:
            attrs['testcase'] = None

        # Create our CrashEntry instance
        return super(CrashEntrySerializer, self).create(attrs)
Exemple #21
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "linux")
        crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testTraceNegativeSizeParam.splitlines())

        testSig = crashInfoPos.createCrashSignature()

        self.assertIn("/ERROR: AddressSanitizer", str(testSig))
        self.assertIn("negative\\\\-size\\\\-param", str(testSig))
        self.assertTrue(isinstance(testSig.symptoms[1], StackFramesSymptom))
Exemple #22
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "windows")
        crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testAsanAccessViolation.splitlines())

        testSig = crashInfoPos.createCrashSignature()

        self.assertIn("/ERROR: AddressSanitizer", str(testSig))
        self.assertIn("access\\\\-violation", str(testSig))
        self.assertTrue(isinstance(testSig.symptoms[1], StackFramesSymptom))
Exemple #23
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "linux")

        crashInfo = ASanCrashInfo([], asanTraceUAF.splitlines(), config)
        self.assertEqual(len(crashInfo.backtrace), 23)
        self.assertEqual(crashInfo.backtrace[0], "void mozilla::PodCopy<char16_t>(char16_t*, char16_t const*, unsigned long)")
        self.assertEqual(crashInfo.backtrace[4], "JSFunction::native() const")
        
        self.assertEqual(crashInfo.crashAddress, 0x7fd766c42800L)
    def runTest(self):
        config = ProgramConfiguration("test", "x86", "linux")
        crashInfoNeg = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testTraceHeapWithCrashAddress.splitlines())
        crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testTraceHeapWithoutCrashAddress.splitlines())

        testSigEmptyCrashAddress = CrashSignature(testSignatureEmptyCrashAddress)

        self.assertTrue(testSigEmptyCrashAddress.matches(crashInfoPos))
        self.assertFalse(testSigEmptyCrashAddress.matches(crashInfoNeg))
Exemple #25
0
def test_SignatureAsanAccessViolationTest():
    config = ProgramConfiguration("test", "x86-64", "windows")
    crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testAsanAccessViolation.splitlines())

    testSig = crashInfoPos.createCrashSignature()

    assert "/ERROR: AddressSanitizer" not in str(testSig)
    assert "access-violation" not in str(testSig)
    assert isinstance(testSig.symptoms[0], StackFramesSymptom)
Exemple #26
0
def test_SignatureStackFramesNegativeSizeParamTest():
    config = ProgramConfiguration("test", "x86-64", "linux")
    crashInfoPos = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testTraceNegativeSizeParam.splitlines())

    testSig = crashInfoPos.createCrashSignature()

    assert "/ERROR: AddressSanitizer" in str(testSig)
    assert "negative-size-param" in str(testSig)
    assert isinstance(testSig.symptoms[1], StackFramesSymptom)
Exemple #27
0
    def runTest(self):
        config = ProgramConfiguration("test", "x86-64", "linux")
        
        crashInfo1 = GDBCrashInfo([], gdbCrashAddress1.splitlines(), config)
        crashInfo2 = GDBCrashInfo([], gdbCrashAddress2.splitlines(), config)
        crashInfo3 = GDBCrashInfo([], gdbCrashAddress3.splitlines(), config)

        self.assertEqual(crashInfo1.crashAddress, 0x1L)
        self.assertEqual(crashInfo2.crashAddress, None)
        self.assertEqual(crashInfo3.crashAddress, 0xffffffffffffffa0L)
Exemple #28
0
def test_SignaturePCREShortTest():
    config = ProgramConfiguration("test", "x86", "linux")

    crashInfo = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testTrace1.splitlines())

    testSig1 = CrashSignature(testSignaturePCREShort1)
    testSig2 = CrashSignature(testSignaturePCREShort2)

    assert testSig1.matches(crashInfo)
    assert not testSig2.matches(crashInfo)
    def runTest(self):
        config = ProgramConfiguration("test", "x86", "linux")

        crashInfo = CrashInfo.fromRawCrashData([], [], config, auxCrashData=testTrace1.splitlines())

        testSig1 = CrashSignature(testSignaturePCREShort1)
        testSig2 = CrashSignature(testSignaturePCREShort2)

        self.assertTrue(testSig1.matches(crashInfo))
        self.assertFalse(testSig2.matches(crashInfo))
Exemple #30
0
def test_SignatureStackFramesRegressionTest():
    config = ProgramConfiguration("test", "x86", "linux")
    crashInfoNeg = CrashInfo.fromRawCrashData([], [], config,
                                              auxCrashData=testTraceHeapWithCrashAddress.splitlines())
    crashInfoPos = CrashInfo.fromRawCrashData([], [], config,
                                              auxCrashData=testTraceHeapWithoutCrashAddress.splitlines())

    testSigEmptyCrashAddress = CrashSignature(testSignatureEmptyCrashAddress)

    assert testSigEmptyCrashAddress.matches(crashInfoPos)
    assert not testSigEmptyCrashAddress.matches(crashInfoNeg)