Repository navigation
Descend into an OEM wrapper archive in check-bugreport - #944
Conversation
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 mvt-project#935
42e8881 to
b1b9958
Compare
|
Rebased onto main after #945 landed. The only conflict was in the import block of |
|
I merged this too early. Foind 2 issues: The empty-success case remains. If the wrapper has no usable nested ZIP, from_zip() keeps the outer archive�. The command can still exit 0 with an empty analysis, contrary to the expected behavior in #935�. It should report that no bug report was found. Descent can discard wrapper-only evidence. The same lines replace the outer ZIP and its file list entirely. The tombstone module can currently read tombstones from the wrapper; #935 reports four such records in one collection. If those files are absent from the inner ZIP, this change silently drops them. That case needs a regression test and a way to retain or explicitly account for those files. |
…-wrapper-archive Descend into an OEM wrapper archive in check-bugreport
Fixes #935
Change,
cmd_check_bugreport.py(+49/−2) andmodules/bugreport/base.py(+10/−3):DUMPSTATE_ENTRY_POINTSmoves intomodules/bugreport/base.py, next to the_get_dumpstate_file()that tries them in that order — so the entry points are named oncerather than once per caller;
_has_dumpstate(file_names)—any(fnmatch.filter(file_names, pattern) for pattern in DUMPSTATE_ENTRY_POINTS), the same matching_get_files_by_pattern()already uses;_nested_bugreport(outer)— only when they are absent: open the outer archive's.zipmembersin memory, names containing
bugreport/dumpstatefirst, and take the first one that doescarry an entry point. Logs which member was used.
The descent is unreachable for an archive that already has an entry point, which is all 30 normal
collections in the test set — including the 27 that carry some other zip member.
On placement: you asked on #935 where this code should live and passed the question to
@DonnchaC. This is my reading of it — the entry points next to the only code that consumes them,
the descent in the command that owns the archive — but nothing here depends on that choice. Say
where you would rather have it and I will move it.
Measured on 44 bug report collections, upstream vs patched — and re-run on the 14 wrappers
after the descent was simplified, with identical totals, so the numbers below come from the code
this PR ships:
tombstones.jsonwith 4 records on the fourteenth; exit 0 throughoutOn the controls, 29 of 30 runs differ byte-for-byte in
timeline.csvandtombstones.jsonand 2of them in
alerts.json; the contents are the same records in a different order, and two runs ofthe same build differ the same way. Record order in those files is not deterministic in
main—worth a separate issue, and worth knowing before anyone uses a checksum to compare two runs.
Tests:
tests/android/test_check_bugreport_wrapper.py, 2 cases — a wrapper is descended into,and a plain archive that merely contains some other zip is left alone.
Applies to
main@777db67with no other change;pytest tests/androidthere goes from 99 passed /1 skipped to 101 passed / 1 skipped.
ruff check,ruff format --checkandmypy --platform linux(156 files) pass on the branch.Related open work (re-checked 2026-09-22, none of these has landed):
modules/bugreport/base.pyfrom_get_files_by_patterns()down (its hunk spans lines 66–226, which contains_get_dumpstate_file()) and also editscmd_check_bugreport.py. If it lands first this PR needsa real rebase, not a context fix.
__init__block ofcmd_check_bugreport.py.new constant sits.
other is a trivial rebase — say the word and I will do it.
archive-discovery defect —
*/packages.jsonnot matching a root-level member — inmodules/androidqf/base.py. No file and no logic in common; worth citing only as theAndroidQF-side analogue.