From ff5ebf73cccf86e2cc1a391443f863e6c6f00593 Mon Sep 17 00:00:00 2001 From: StarRailHub <3151336214@qq.com> Date: Wed, 23 Sep 2026 12:11:58 +0800 Subject: [PATCH 1/4] fix: parse dumpsys ADB output with CRLF line endings --- src/mvt/android/artifacts/dumpsys_adb.py | 12 ++++++++++-- tests/android/test_artifact_dumpsys_adb.py | 12 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/mvt/android/artifacts/dumpsys_adb.py b/src/mvt/android/artifacts/dumpsys_adb.py index cbd80e21..f2b68bcc 100644 --- a/src/mvt/android/artifacts/dumpsys_adb.py +++ b/src/mvt/android/artifacts/dumpsys_adb.py @@ -29,7 +29,8 @@ class DumpsysADBArtifact(AndroidArtifact): stack = [res] cur_indent = 0 in_multiline = False - for line in dump_data.strip(b"\n").split(b"\n"): + for line in dump_data.strip(b"\r\n").split(b"\n"): + line = line.removesuffix(b"\r") # Track the level of indentation indent = len(line) - len(line.lstrip()) if indent < cur_indent: @@ -180,12 +181,19 @@ class DumpsysADBArtifact(AndroidArtifact): self.log.error("Unable to find ADB manager state in dumpsys output") return + line_ending_length = 1 end_of_json = content.rfind(b"}\n") + crlf_end_of_json = content.rfind(b"}\r\n") + if crlf_end_of_json > end_of_json: + line_ending_length = 2 + end_of_json = crlf_end_of_json if end_of_json == -1 or end_of_json <= start_of_json: self.log.error("Unable to find complete ADB manager state in dumpsys output") return - json_content = content[start_of_json + 2 : end_of_json - 2].rstrip() + json_content = content[ + start_of_json + 2 : end_of_json - line_ending_length - 1 + ].rstrip() parsed = self.indented_dump_parser(json_content) if parsed.get("debugging_manager") is None: diff --git a/tests/android/test_artifact_dumpsys_adb.py b/tests/android/test_artifact_dumpsys_adb.py index 8d501b7d..beeaba3a 100644 --- a/tests/android/test_artifact_dumpsys_adb.py +++ b/tests/android/test_artifact_dumpsys_adb.py @@ -130,6 +130,18 @@ class TestDumpsysADBArtifact: assert key_store_entry["fingerprint"] == expected_fingerprint assert key_store_entry["last_connected"] == "1628501829898" + def test_parsing_adb_xml_with_crlf_line_endings(self): + da_adb = DumpsysADBArtifact() + file = get_artifact("android_data/dumpsys_adb_xml.txt") + with open(file, "rb") as f: + data = f.read().replace(b"\r\n", b"\n").replace(b"\n", b"\r\n") + + da_adb.parse(data) + + assert len(da_adb.results) == 1 + assert da_adb.results[0]["user_keys"][0]["user"] == "user@laptop" + assert da_adb.results[0]["keystore"][0]["last_connected"] == "1628501829898" + class TestDumpsysADBStateAlerts: def test_no_androidqf_context_preserves_existing_behavior(self): From 8c5278f5405ceb26889428166b3c1fe43fa32879 Mon Sep 17 00:00:00 2001 From: besendorf Date: Thu, 24 Sep 2026 04:37:25 -0700 Subject: [PATCH 2/4] Refactor JSON extraction logic in dumpsys_adb.py --- src/mvt/android/artifacts/dumpsys_adb.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/mvt/android/artifacts/dumpsys_adb.py b/src/mvt/android/artifacts/dumpsys_adb.py index f2b68bcc..ac397cfb 100644 --- a/src/mvt/android/artifacts/dumpsys_adb.py +++ b/src/mvt/android/artifacts/dumpsys_adb.py @@ -181,19 +181,18 @@ class DumpsysADBArtifact(AndroidArtifact): self.log.error("Unable to find ADB manager state in dumpsys output") return - line_ending_length = 1 - end_of_json = content.rfind(b"}\n") - crlf_end_of_json = content.rfind(b"}\r\n") - if crlf_end_of_json > end_of_json: - line_ending_length = 2 - end_of_json = crlf_end_of_json + end_of_json = max(content.rfind(b"}\n"), content.rfind(b"}\r\n")) if end_of_json == -1 or end_of_json <= start_of_json: self.log.error("Unable to find complete ADB manager state in dumpsys output") return - json_content = content[ - start_of_json + 2 : end_of_json - line_ending_length - 1 - ].rstrip() + # Exclude the final nested closing brace regardless of its line ending. + # The indented parser finishes the open debugging_manager at EOF. + inner_end = content.rfind(b"}", start_of_json + 2, end_of_json) + if inner_end == -1: + self.log.error("Unable to find complete ADB manager state in dumpsys output") + return + json_content = content[start_of_json + 2 : inner_end].rstrip() parsed = self.indented_dump_parser(json_content) if parsed.get("debugging_manager") is None: From f1e52b297a0d97ebbf6af037c136b1080f7ab2e8 Mon Sep 17 00:00:00 2001 From: besendorf Date: Thu, 24 Sep 2026 04:40:48 -0700 Subject: [PATCH 3/4] test: cover mixed ADB state line endings Regression for CRLF after the manager brace and LF after the outer brace. --- tests/android/test_artifact_dumpsys_adb.py | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/android/test_artifact_dumpsys_adb.py b/tests/android/test_artifact_dumpsys_adb.py index beeaba3a..3f6f892d 100644 --- a/tests/android/test_artifact_dumpsys_adb.py +++ b/tests/android/test_artifact_dumpsys_adb.py @@ -143,6 +143,29 @@ class TestDumpsysADBArtifact: assert da_adb.results[0]["keystore"][0]["last_connected"] == "1628501829898" + def test_parsing_adb_wifi_with_mixed_line_endings(self): + da_adb = DumpsysADBArtifact() + data = ( + b"ADB MANAGER STATE (dumpsys adb):\n" + b"{\n" + b" debugging_manager={\n" + b" connected_to_adb=true\n" + b" user_keys=QUJDRA== host@example\n" + b" adb_wifi={\n" + b" enabled=false\n" + b" }\n" + b" }\r\n" + b"}\n" + b"--------- duration\n" + ) + + da_adb.parse(data) + + assert len(da_adb.results) == 1 + assert da_adb.results[0]["user_keys"][0]["user"] == "host@example" + assert da_adb.results[0]["adb_wifi"]["enabled"] == b"false" + + class TestDumpsysADBStateAlerts: def test_no_androidqf_context_preserves_existing_behavior(self): module = DumpsysADBState( From 9ca4254649a104fcd14420f1bb5a832c47702bfc Mon Sep 17 00:00:00 2001 From: besendorf Date: Thu, 24 Sep 2026 09:38:18 -0700 Subject: [PATCH 4/4] Fix formatting in test_artifact_dumpsys_adb.py --- tests/android/test_artifact_dumpsys_adb.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/android/test_artifact_dumpsys_adb.py b/tests/android/test_artifact_dumpsys_adb.py index 3f6f892d..2fcd0bba 100644 --- a/tests/android/test_artifact_dumpsys_adb.py +++ b/tests/android/test_artifact_dumpsys_adb.py @@ -142,7 +142,6 @@ class TestDumpsysADBArtifact: assert da_adb.results[0]["user_keys"][0]["user"] == "user@laptop" assert da_adb.results[0]["keystore"][0]["last_connected"] == "1628501829898" - def test_parsing_adb_wifi_with_mixed_line_endings(self): da_adb = DumpsysADBArtifact() data = (