Example #1
0
    def createShortSignature(self):
        '''
        @rtype: String
        @return: A string representing this crash (short signature)
        '''
        # Always prefer using regular program aborts
        abortMsg = AssertionHelper.getAssertion(self.rawStderr)

        # Also check the crash data for program abort data
        # (sometimes happens e.g. with MOZ_CRASH)
        if not abortMsg and self.rawCrashData:
            abortMsg = AssertionHelper.getAssertion(self.rawCrashData)

        if abortMsg != None:
            if isinstance(abortMsg, list):
                return " ".join(abortMsg)
            else:
                return abortMsg

        # If we don't have a program abort message, see if we have an ASan
        # specific abort message other than a crash message that we can use.
        abortMsg = AssertionHelper.getAuxiliaryAbortMessage(self.rawStderr)

        # Also check the crash data again
        if not abortMsg and self.rawCrashData:
            abortMsg = AssertionHelper.getAuxiliaryAbortMessage(self.rawCrashData)

        if abortMsg != None:
            rwMsg = None
            if isinstance(abortMsg, list):
                asanMsg = abortMsg[0]
                rwMsg = abortMsg[1]
            else:
                asanMsg = abortMsg

            # Do some additional formatting work for short signature only
            asanMsg = re.sub("^ERROR: ", "", asanMsg)

            # Strip various forms of special thread information and messages
            asanMsg = re.sub(" in thread T.+", "", asanMsg)
            asanMsg = re.sub(" malloc\(\)\-ed: 0x[0-9a-f]+", r" malloc()-ed", asanMsg)

            if len(self.backtrace):
                asanMsg += " [@ %s]" % self.backtrace[0]
            if rwMsg:
                # Strip address and thread
                rwMsg = re.sub(" at 0x[0-9a-f]+ thread .+", "", rwMsg)
                asanMsg += " with %s" % rwMsg

            return asanMsg

        if not len(self.backtrace):
            return "No crash detected"

        return "[@ %s]" % self.backtrace[0]
    def runTest(self):
        err = asanStackOverflow.splitlines()

        assert AssertionHelper.getAssertion(err) is None
        assertMsg = AssertionHelper.getAuxiliaryAbortMessage(err)
        expectedAssertMsg = "ERROR: AddressSanitizer: stack-overflow"
        assert assertMsg == expectedAssertMsg
Example #3
0
def test_AssertionHelperTestASanStackOverflow():
    err = asanStackOverflow.splitlines()

    assert AssertionHelper.getAssertion(err) is None
    assertMsg = AssertionHelper.getAuxiliaryAbortMessage(err)
    expectedAssertMsg = "ERROR: AddressSanitizer: stack-overflow"
    assert assertMsg == expectedAssertMsg
Example #4
0
def test_AssertionHelperTestASanNegativeSize():
    err = asanNegativeSize.splitlines()

    assert AssertionHelper.getAssertion(err) is None
    assertMsg = AssertionHelper.getSanitizedAssertionPattern(AssertionHelper.getAuxiliaryAbortMessage(err))
    expectedAssertMsg = r"ERROR: AddressSanitizer: negative-size-param: \(size=-[0-9]{2,}\)"
    assert assertMsg == expectedAssertMsg
    def runTest(self):
        err = asanStackOverflow.splitlines()

        self.assertEqual(AssertionHelper.getAssertion(err), None)
        assertMsg = AssertionHelper.getAuxiliaryAbortMessage(err)
        expectedAssertMsg = "ERROR: AddressSanitizer: stack-overflow"
        self.assertEqual(assertMsg, expectedAssertMsg)
    def runTest(self):
        err = asanNegativeSize.splitlines()

        self.assertEqual(AssertionHelper.getAssertion(err), None)
        assertMsg = AssertionHelper.getSanitizedAssertionPattern(AssertionHelper.getAuxiliaryAbortMessage(err))
        expectedAssertMsg = r"ERROR: AddressSanitizer: negative\-size\-param: \(size=\-[0-9]{2,}\)"
        self.assertEqual(assertMsg, expectedAssertMsg)
    def runTest(self):
        err = asanNegativeSize.splitlines()

        assert AssertionHelper.getAssertion(err) is None
        assertMsg = AssertionHelper.getSanitizedAssertionPattern(AssertionHelper.getAuxiliaryAbortMessage(err))
        expectedAssertMsg = r"ERROR: AddressSanitizer: negative-size-param: \(size=-[0-9]{2,}\)"
        assert assertMsg == expectedAssertMsg
    def runTest(self):
        err = asanOverflow.splitlines()

        sanitizedMsg = AssertionHelper.getSanitizedAssertionPattern(AssertionHelper.getAuxiliaryAbortMessage(err))
        expectedMsg = [
             "ERROR: AddressSanitizer: heap\\-buffer\\-overflow",
             "READ of size 8 at 0x[0-9a-fA-F]+ thread T[0-9]{2,} \\(MediaPlayback #1\\)"
             ]

        self.assertEqual(sanitizedMsg, expectedMsg)
Example #9
0
    def runTest(self):
        err = asanOverflow.splitlines()

        sanitizedMsg = AssertionHelper.getSanitizedAssertionPattern(AssertionHelper.getAuxiliaryAbortMessage(err))
        expectedMsg = [
             "ERROR: AddressSanitizer: heap\\-buffer\\-overflow",
             "READ of size 8 at 0x[0-9a-fA-F]+ thread T[0-9]{2,} \\(MediaPlayback #1\\)"
             ]

        self.assertEqual(sanitizedMsg, expectedMsg)
Example #10
0
def test_AssertionHelperTestAuxiliaryAbortASan():
    err = asanOverflow.splitlines()

    sanitizedMsg = AssertionHelper.getSanitizedAssertionPattern(AssertionHelper.getAuxiliaryAbortMessage(err))
    expectedMsg = [
        r"ERROR: AddressSanitizer: heap-buffer-overflow",
        r"READ of size 8 at 0x[0-9a-fA-F]+ thread T[0-9]{2,} \(MediaPlayback #1\)"
    ]

    assert sanitizedMsg == expectedMsg
    _check_regex_matches(err, sanitizedMsg)
    def runTest(self):
        err = asanOverflow.splitlines()

        sanitizedMsg = AssertionHelper.getSanitizedAssertionPattern(AssertionHelper.getAuxiliaryAbortMessage(err))
        expectedMsg = [
            r"ERROR: AddressSanitizer: heap-buffer-overflow",
            r"READ of size 8 at 0x[0-9a-fA-F]+ thread T[0-9]{2,} \(MediaPlayback #1\)"
        ]

        assert sanitizedMsg == expectedMsg
        _check_regex_matches(err, sanitizedMsg)
Example #12
0
    def createShortSignature(self):
        '''
        @rtype: String
        @return: A string representing this crash (short signature)
        '''
        # Try to find the UBSan message on stderr and use that as short signature
        abortMsg = AssertionHelper.getAuxiliaryAbortMessage(self.rawStderr)

        # See if we have it in our crash data maybe instead
        if not abortMsg and self.rawCrashData:
            abortMsg = AssertionHelper.getAuxiliaryAbortMessage(self.rawCrashData)

        if abortMsg != None:
            if isinstance(abortMsg, list):
                return "UndefinedBehaviorSanitizer: %s" % " ".join(abortMsg)
            else:
                return "UndefinedBehaviorSanitizer: %s" % abortMsg

        if not len(self.backtrace):
            return "No crash detected"

        return "UndefinedBehaviorSanitizer: [@ %s]" % self.backtrace[0]
Example #13
0
    def runTest(self):
        err = asanOverflow.splitlines()

        sanitizedMsg = AssertionHelper.getSanitizedAssertionPattern(
            AssertionHelper.getAuxiliaryAbortMessage(err))
        expectedMsg = [
            "ERROR: AddressSanitizer: heap\\-buffer\\-overflow",
            "READ of size 8 at 0x[0-9a-fA-F]+ thread T[0-9]{2,} \\(MediaPlayback #1\\)"
        ]

        self.assertEqual(sanitizedMsg, expectedMsg)

        # Ensure the sanitized messages can be compiled as regex without errors
        re.compile(sanitizedMsg[0])
        re.compile(sanitizedMsg[1])
Example #14
0
def test_AssertionHelperTestASanFFAbort():
    err = asanFFAbort.splitlines()

    assert AssertionHelper.getAssertion(err) is None
    assert AssertionHelper.getAuxiliaryAbortMessage(err) is None
Example #15
0
    def runTest(self):
        err = asanFFAbort.splitlines()

        assert AssertionHelper.getAssertion(err) is None
        assert AssertionHelper.getAuxiliaryAbortMessage(err) is None
Example #16
0
    def createCrashSignature(self, forceCrashAddress=False, forceCrashInstruction=False, maxFrames=8, minimumSupportedVersion=13):
        '''
        @param forceCrashAddress: If True, the crash address will be included in any case
        @type forceCrashAddress: bool
        @param forceCrashInstruction: If True, the crash instruction will be included in any case
        @type forceCrashInstruction: bool
        @param maxFrames: How many frames (at most) should be included in the signature
        @type maxFrames: int

        @param minimumSupportedVersion: The minimum crash signature standard version that the
                                        generated signature should be valid for (10 => 1.0, 13 => 1.3)
        @type minimumSupportedVersion: int

        @rtype: CrashSignature
        @return: A crash signature object
        '''
        # Determine the actual number of frames based on how many we got
        if len(self.backtrace) > maxFrames:
            numFrames = maxFrames
        else:
            numFrames = len(self.backtrace)

        symptomArr = []

        # Memorize where we find our abort messages
        abortMsgInCrashdata = False

        # See if we have an abort message and if so, get a sanitized version of it
        abortMsgs = AssertionHelper.getAssertion(self.rawStderr)

        if abortMsgs is None and minimumSupportedVersion >= 13:
            # Look for abort messages also inside crashdata
            # only on version 1.3 or higher, because the "crashdata" source
            # type for output matching was added in that version.
            abortMsgs = AssertionHelper.getAssertion(self.rawCrashData)
            if abortMsgs != None:
                abortMsgInCrashdata = True

        # Still no abort message, fall back to auxiliary abort messages (ASan/UBSan)
        if abortMsgs is None:
            abortMsgs = AssertionHelper.getAuxiliaryAbortMessage(self.rawStderr)

        if abortMsgs is None and minimumSupportedVersion >= 13:
            # Look for auxiliary abort messages also inside crashdata
            # only on version 1.3 or higher, because the "crashdata" source
            # type for output matching was added in that version.
            abortMsgs = AssertionHelper.getAuxiliaryAbortMessage(self.rawCrashData)
            if abortMsgs != None:
                abortMsgInCrashdata = True

        if abortMsgs != None:
            if not isinstance(abortMsgs, list):
                abortMsgs = [abortMsgs]

            for abortMsg in abortMsgs:
                abortMsg = AssertionHelper.getSanitizedAssertionPattern(abortMsg)
                abortMsgSrc = "stderr"
                if abortMsgInCrashdata:
                    abortMsgSrc = "crashdata"

                # Compose StringMatch object with PCRE pattern.
                # Versions below 1.2 only support the full object PCRE style,
                # for anything newer, use the short form with forward slashes
                # to increase the readability of the signatures.
                if minimumSupportedVersion < 12:
                    stringObj = { "value" : abortMsg, "matchType" : "pcre" }
                    symptomObj = { "type" : "output", "src" : abortMsgSrc, "value" : stringObj }
                else:
                    symptomObj = { "type" : "output", "src" : abortMsgSrc, "value" : "/%s/" % abortMsg }
                symptomArr.append(symptomObj)

        # Consider the first four frames as top stack
        topStackLimit = 4

        # If we have less than topStackLimit frames available anyway, count the difference
        # between topStackLimit and the available frames already as missing.
        # E.g. if the trace has only three entries anyway, one will be considered missing
        # right from the start. This should prevent that very short stack frames are used
        # for signatures without additional crash information that narrows the signature.

        if numFrames >= topStackLimit:
            topStackMissCount = 0
        else:
            topStackMissCount = topStackLimit - numFrames

        # StackFramesSymptom is only supported in 1.2 and higher,
        # for everything else, use multiple stackFrame symptoms
        if minimumSupportedVersion < 12:
            for idx in range(0, numFrames):
                functionName = self.backtrace[idx]
                if not functionName == "??":
                    symptomObj = { "type" : "stackFrame", "frameNumber" : idx, "functionName" : functionName }
                    symptomArr.append(symptomObj)
                elif idx < 4:
                    # If we're in the top 4, we count this as a miss
                    topStackMissCount += 1
        else:
            framesArray = []

            for idx in range(0, numFrames):
                functionName = self.backtrace[idx]
                if not functionName == "??":
                    framesArray.append(functionName)
                else:
                    framesArray.append("?")
                    if idx < 4:
                        # If we're in the top 4, we count this as a miss
                        topStackMissCount += 1

            lastSymbolizedFrame = None
            for frameIdx in range(0, len(framesArray)):
                if str(framesArray[frameIdx]) != '?':
                    lastSymbolizedFrame = frameIdx

            if lastSymbolizedFrame != None:
                # Remove all elements behind the last symbolized frame
                framesArray = framesArray[:lastSymbolizedFrame + 1]
            else:
                # We don't have a single symbolized frame, so it doesn't make sense
                # to keep any wildcards in case we added some for unsymbolized frames.
                framesArray = []

            if framesArray:
                symptomArr.append({ "type" : "stackFrames", "functionNames" : framesArray })

        # Missing too much of the top stack frames, add additional crash information
        stackIsInsufficient = topStackMissCount >= 2 and abortMsgs == None

        includeCrashAddress = stackIsInsufficient or forceCrashAddress
        includeCrashInstruction = (stackIsInsufficient and self.crashInstruction != None) or forceCrashInstruction

        if includeCrashAddress:
            if self.crashAddress == None:
                crashAddress = ""
            elif self.crashAddress != 0L and self.crashAddress < 0x100L:
                # Try to match crash addresses that are small but non-zero
                # with a generic range that is likely associated with null-deref.
                crashAddress = "< 0x100"
            else:
                crashAddress = hex(self.crashAddress).rstrip("L")

            crashAddressSymptomObj = { "type" : "crashAddress", "address" : crashAddress }
            symptomArr.append(crashAddressSymptomObj)
Example #17
0
    def runTest(self):
        err = asanFFAbort.splitlines()

        self.assertEqual(AssertionHelper.getAssertion(err), None)
        self.assertEqual(AssertionHelper.getAuxiliaryAbortMessage(err), None)
Example #18
0
    def runTest(self):
        err = asanFFAbort.splitlines()

        self.assertEqual(AssertionHelper.getAssertion(err), None)
        self.assertEqual(AssertionHelper.getAuxiliaryAbortMessage(err), None)
    def runTest(self):
        err = asanFFAbort.splitlines()

        assert AssertionHelper.getAssertion(err) is None
        assert AssertionHelper.getAuxiliaryAbortMessage(err) is None