mirror of
https://github.com/mvt-project/mvt.git
synced 2026-10-02 05:59:39 +02:00
MIUI / HyperOS hands out a zip of app logs, ANR traces and tcpdump captures with the real bugreport-<device>-<timestamp>.zip nested inside. The outer archive carries none of the entry points the bug report modules read, so every module reported it found no files and check-bugreport still exited 0 with an empty result — an empty analysis that looks like a finished one. Name the entry points once in modules/bugreport/base.py, next to the _get_dumpstate_file() that tries them, and when an archive has none of them, open its zip members in memory and use the first one that does. Measured over 44 bug report collections: the 14 wrapper collections go from 0 artifacts to 260 artifacts and 586638 records; the 30 normal collections are unchanged, the descent being unreachable for them. Fixes #935
57 lines
2.2 KiB
Python
57 lines
2.2 KiB
Python
# Mobile Verification Toolkit (MVT)
|
|
# Copyright (c) 2021-2023 The MVT Authors.
|
|
# Use of this software is governed by the MVT License 1.1 that can be found at
|
|
# https://license.mvt.re/1.1/
|
|
"""An OEM wrapper archive must not read as an empty bug report.
|
|
|
|
MIUI / HyperOS hands out a zip of app logs with the real
|
|
`bugreport-<device>-<timestamp>.zip` nested inside. The outer archive has
|
|
none of the entry points the modules read, so every module
|
|
reported it found nothing and the command still exited 0 — an empty analysis
|
|
that looks like a finished one.
|
|
"""
|
|
|
|
import io
|
|
import zipfile
|
|
|
|
from mvt.android.cmd_check_bugreport import CmdAndroidCheckBugreport
|
|
|
|
DUMPSTATE = "== dumpstate: 2026-01-01 00:00:00\nDUMP OF SERVICE package:\n"
|
|
|
|
|
|
def _inner_zip() -> bytes:
|
|
buffer = io.BytesIO()
|
|
with zipfile.ZipFile(buffer, "w") as inner:
|
|
inner.writestr("main_entry.txt", "bugreport-test-2026-01-01-00-00-00.txt")
|
|
inner.writestr("bugreport-test-2026-01-01-00-00-00.txt", DUMPSTATE)
|
|
return buffer.getvalue()
|
|
|
|
|
|
def _wrapper_zip() -> zipfile.ZipFile:
|
|
buffer = io.BytesIO()
|
|
with zipfile.ZipFile(buffer, "w") as outer:
|
|
outer.writestr("app_logs/hilog.txt", "unrelated OEM log\n")
|
|
outer.writestr("bugreport-test-2026-01-01-00-00-00.zip", _inner_zip())
|
|
return zipfile.ZipFile(io.BytesIO(buffer.getvalue()))
|
|
|
|
|
|
class TestCheckBugreportWrapper:
|
|
def test_nested_bugreport_is_used(self, tmp_path):
|
|
cmd = CmdAndroidCheckBugreport(results_path=str(tmp_path))
|
|
cmd.from_zip(_wrapper_zip())
|
|
module = cmd.modules[0](results_path=str(tmp_path))
|
|
cmd.module_init(module)
|
|
assert "main_entry.txt" in module.zip_files
|
|
|
|
def test_plain_bugreport_is_left_alone(self, tmp_path):
|
|
buffer = io.BytesIO()
|
|
with zipfile.ZipFile(buffer, "w") as archive:
|
|
archive.writestr("main_entry.txt", "bugreport.txt")
|
|
archive.writestr("bugreport.txt", DUMPSTATE)
|
|
archive.writestr("attachments/extra.zip", _inner_zip())
|
|
cmd = CmdAndroidCheckBugreport(results_path=str(tmp_path))
|
|
cmd.from_zip(zipfile.ZipFile(io.BytesIO(buffer.getvalue())))
|
|
module = cmd.modules[0](results_path=str(tmp_path))
|
|
cmd.module_init(module)
|
|
assert "attachments/extra.zip" in module.zip_files
|