From d92a60c9bea7495c99fc3cb2758b7710833b4d03 Mon Sep 17 00:00:00 2001 From: besendorf Date: Mon, 10 Aug 2026 20:59:56 +0200 Subject: [PATCH] Preserve tombstone crash causes (#863) --- .../android/artifacts/tombstone_crashes.py | 3 ++ tests/android/test_artifact_tombstones.py | 42 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/mvt/android/artifacts/tombstone_crashes.py b/src/mvt/android/artifacts/tombstone_crashes.py index d4888ef..bcfb389 100644 --- a/src/mvt/android/artifacts/tombstone_crashes.py +++ b/src/mvt/android/artifacts/tombstone_crashes.py @@ -34,6 +34,7 @@ TOMBSTONE_TEXT_KEY_MAPPINGS = { "signal": "signal_info", "code": "code", "Cause": "cause", + "Abort message": "abort_message", } @@ -67,6 +68,8 @@ class TombstoneCrashResult(pydantic.BaseModel): uid: int signal_info: SignalInfo cause: Optional[str] = None + causes: Optional[List[dict]] = None + abort_message: Optional[str] = None extra: Optional[str] = None diff --git a/tests/android/test_artifact_tombstones.py b/tests/android/test_artifact_tombstones.py index e4e51cf..f88a9c2 100644 --- a/tests/android/test_artifact_tombstones.py +++ b/tests/android/test_artifact_tombstones.py @@ -8,6 +8,7 @@ import datetime import pytest from mvt.android.artifacts.tombstone_crashes import TombstoneCrashArtifact +from mvt.android.parsers.proto.tombstone import Tombstone from ..utils import get_artifact @@ -42,6 +43,47 @@ class TestTombstoneCrashArtifact: assert len(tombstone_artifact.results) == 1 self.validate_tombstone_result(tombstone_artifact.results[0]) + def test_text_tombstone_preserves_abort_message(self): + tombstone_artifact = TombstoneCrashArtifact() + artifact_path = "android_data/bugreport/FS/data/tombstones/tombstone_00" + file = get_artifact(artifact_path) + with open(file, "rb") as f: + data = f.read() + + tombstone_artifact.parse( + os.path.basename(artifact_path), + datetime.datetime(2021, 9, 29, 17, 43, 49), + data, + ) + + assert tombstone_artifact.results[0]["abort_message"] == ( + "Check failed: payload.size() <= bytes_left " + "(payload.size()=99, bytes_left=51) " + ) + + def test_protobuf_tombstone_preserves_abort_message_and_causes(self): + tombstone_artifact = TombstoneCrashArtifact() + artifact_path = "android_data/tombstone_process.pb" + file = get_artifact(artifact_path) + with open(file, "rb") as f: + tombstone = Tombstone().parse(f.read()) + + tombstone.abort_message = "synthetic abort reason" + tombstone_artifact.parse_protobuf( + os.path.basename(artifact_path), + datetime.datetime(2023, 4, 12, 12, 32, 40, 518290), + bytes(tombstone), + ) + + result = tombstone_artifact.results[0] + assert result["abort_message"] == "synthetic abort reason" + assert result["causes"] == [ + { + "human_readable": "null pointer dereference", + "memory_error": None, + } + ] + def test_text_tombstone_keeps_crashing_thread(self): tombstone_artifact = TombstoneCrashArtifact() artifact_path = "android_data/tombstone_process.txt"