Unpack .tar.bz2 and .tar.xz, which only half-extracted
formatOf matched .tar.gz/.tgz as a combined format and then fell through to the bare .bz2 and .xz wrappers, so a .tar.bz2 was read as one compressed file: extracting it decompressed a single layer and left a .tar to extract again, while the same archive named .tar.gz unpacked in one step. The store listing advertised "extract ZIP, TAR, TAR.GZ, GZ, BZ2, XZ and 7z", which reads as though they all behave alike. Found by extracting one archive of every supported format through the UI on the API 35 AVD rather than trusting the suite. A real z4.tar.bz2 left z4/z4.tar - raw ustar headers and all - beside z3.tar.gz fully unpacked to z3/a.txt and z3/sub/b.txt. TAR_BZIP2 and TAR_XZ now sit alongside TAR_GZIP, detection consumes the whole tar suffix (.tar.bz2/.tbz2, .tar.xz/.txz) before the bare compressor, and the engine gains the two readArchive branches. The bare spellings still mean a single compressed file. The suite had a gap that let this hide: only ZIP, GZIP, XZ and 7z had round-trip tests, so neither plain TAR nor TAR_GZIP did, and there was nothing for the asymmetry to contradict. All four tar spellings have one now, built in memory with the same library that reads them. 212 JVM tests, lint clean. Also records the format sweep in EDGE_CASE_TESTING and re-measures the release artefacts (aab 4 838 235 / sha256 e1d23130..., apk 2 155 455 / sha256 37fb46cb...). The APK byte count happened to land on the same figure as the previous build, so the new literals were confirmed present in the shipped dex rather than trusted to the size.
This commit is contained in:
@@ -66,6 +66,7 @@ track to report back.
|
||||
| The progress notification | **Fixed, then verified.** After the fix, a real 220 MB copy posts notification `1001` on channel `file-operations` with `ONGOING_EVENT\|NO_CLEAR\|FOREGROUND_SERVICE` and `category=progress`, then removes it and stops the service when the copy finishes. Before the fix the app's notification importance was `NONE`. |
|
||||
| Copy to completion | The staged copy landed at `/sdcard/bigfile.bin`, byte-count identical, via the overflow menu's "Paste here". |
|
||||
| Compress and extract from the UI | **Found a bug, fixed.** Long-pressing a folder and choosing "Compress to ZIP" produced a `tocompress.zip` that the host's `unzip` read back with the right relative paths and contents. Selecting that `.zip` then exposed the selection bar clipping its own actions — see below. |
|
||||
| One archive of **every** supported format | **Found a bug, fixed.** A real `.zip`, `.7z`, `.tar`, `.tar.gz`, `.tar.bz2`, `.txt.xz`, `.txt.gz` and `.txt.bz2` were built on the host and all eight extracted through the UI. Each landed with the right entry names and byte-for-byte content — except `.tar.bz2`, which produced a bare `.tar`, recorded below. |
|
||||
| Long-press from adb | `input swipe x y x y 700` on a single point *did* open the selection bar and reach Copy. The same gesture has been flaky on the MIUI phone, so it still deserves a manual pass. |
|
||||
|
||||
### The bugs this session found
|
||||
@@ -100,6 +101,16 @@ everything at once, which is honest but not ideal — moving the two least-used
|
||||
Clear selection) into the overflow menu would be the better fix, and is left as deliberate
|
||||
follow-up rather than bundled in here.
|
||||
|
||||
**`.tar.bz2` and `.tar.xz` only half-extracted.** `ArchiveFormats.formatOf` tested `.tar.gz`/`.tgz`
|
||||
first, as a combined format, but then matched `.bz2` and `.xz` *before* it ever considered the
|
||||
`.tar` in the middle of the name — so a `.tar.gz` unpacked to its files while a `.tar.bz2` was
|
||||
read as one compressed file and yielded a `.tar`. Driving the sweep made it exact: extracting
|
||||
`z4.tar.bz2` left `z4/z4.tar`, raw `ustar` headers and all, beside `z3.tar.gz`'s fully unpacked
|
||||
`z3/a.txt` and `z3/sub/b.txt`. `TAR_BZIP2` and `TAR_XZ` now exist alongside `TAR_GZIP`, and
|
||||
detection consumes the whole tar suffix before the bare compressor. The suite could not have
|
||||
caught this: only ZIP, GZIP, XZ and 7z had round-trip tests, so neither plain `TAR` nor
|
||||
`TAR_GZIP` did, and there was nothing for the asymmetry to contradict. All four have one now.
|
||||
|
||||
The lesson is the one the phone already taught twice: a green test suite says the code does
|
||||
what the tests describe, not that the app does anything on a device. Both times the gap was a
|
||||
user-visible promise the code no longer kept — once in a dialog, once in a permission.
|
||||
@@ -118,8 +129,10 @@ user-visible promise the code no longer kept — once in a dialog, once in a per
|
||||
- **The foreground-service notification** during a long copy. **Now observed** on the API 35 AVD
|
||||
(see above), including its teardown — so what is left unverified is a *physical* device, where
|
||||
the system may defer or kill a background `dataSync` service on its own schedule.
|
||||
- **Archive creation/extraction against real files.** Now driven end-to-end on the API 35 AVD: a
|
||||
folder of three files compressed to a `.zip` that the host's `unzip` read back with the right
|
||||
relative paths and contents, and that `.zip` then selected for extraction. What is still
|
||||
untested is the exotic end of the format list — 7z, `.xz`, the tar wrappers — against real
|
||||
files rather than the fixtures the JVM tests build.
|
||||
- **Archive creation/extraction against real files.** Driven end-to-end on the API 35 AVD, one
|
||||
archive of every supported format: `ZIP`, `7z`, `TAR`, `TAR.GZ`, `TAR.BZ2`, `TAR.XZ`, `GZ`,
|
||||
`BZ2` and `XZ` all extracted through the UI with the right entry names and byte-for-byte
|
||||
contents, and a folder compressed to a `.zip` that the host's `unzip` read back. That sweep is
|
||||
what found the `.tar.bz2` asymmetry fixed above. Still untested: a *hostile* archive on a
|
||||
device — the zip-slip and 7z-slip cases are JVM-only — and RAR/CAB/ISO/WIM, which the app
|
||||
refuses by design.
|
||||
|
||||
@@ -42,20 +42,23 @@ rest are things you must do in the Play Console or with your own accounts.
|
||||
|
||||
- [x] **[code] re-verified 2026-10-15.** `bundleRelease` and `assembleRelease` both succeed
|
||||
with R8 minification and resource shrinking on.
|
||||
- `app-release.aab` is **4 837 465 bytes**
|
||||
(`sha256 9c2b3a007784297511f29b107a3be40e648709d7702315c53b93ef18f5979070`).
|
||||
- `app-release.apk` is **2 155 455 bytes**, signed by the upload key above.
|
||||
- `app-release.aab` is **4 838 235 bytes**
|
||||
(`sha256 e1d23130b307345b1147e5cf54413d42ed53a1693e0682464cd1b64552e0ea78`).
|
||||
- `app-release.apk` is **2 155 455 bytes**
|
||||
(`sha256 37fb46cb3ef4908b73a9147442ff3f93905a893b8ddd27abb9e02610139a8cee`),
|
||||
signed by the upload key above.
|
||||
- Both report `versionCode=1 versionName=1.0.0 targetSdk=36` and exactly the
|
||||
permission set in step 4 — **no `INTERNET`**, so "nothing leaves the device" holds
|
||||
in the shipped artefact and not just in the source manifest.
|
||||
- The figures barely moved again, but the permission set did: the four `READ_MEDIA_*`
|
||||
declarations are gone, removed once the Android 15 pass showed the app never
|
||||
requested them and never read through `MediaStore` (see below). Four manifest lines
|
||||
are worth only a few hundred bytes, hence 4 837 465 rather than a visible drop; the
|
||||
first measurement was 4 682 814 / 2 081 955, before the LZMA library behind `.xz`
|
||||
and 7z. The permission set has only ever shrunk: the share target, the file picker,
|
||||
the trash index and the archive work all arrived without a single new permission,
|
||||
which is the point of having designed them that way.
|
||||
requested them and never read through `MediaStore` (see below), together with the
|
||||
archive fix for `.tar.bz2`/`.tar.xz`. Small source changes barely register in a
|
||||
bundle dominated by libraries, hence 4 838 235 rather than a visible drop; the first
|
||||
measurement was 4 682 814 / 2 081 955, before the LZMA library behind `.xz` and 7z.
|
||||
The permission set has only ever shrunk: the share target, the file picker, the
|
||||
trash index and the archive work all arrived without a single new permission, which
|
||||
is the point of having designed them that way.
|
||||
- ⚠️ **Re-measure after any further change.** These numbers are a record of a verified
|
||||
artefact, not a constant — a stale hash here is worse than no hash, because it looks
|
||||
checked.
|
||||
|
||||
@@ -114,7 +114,7 @@ FIND OUT WHERE THE SPACE WENT
|
||||
• Spot the folder that is actually eating your storage, then act on it
|
||||
|
||||
ARCHIVES
|
||||
• Create ZIP archives, and extract ZIP, TAR, TAR.GZ, GZ, BZ2, XZ and 7z
|
||||
• Create ZIP archives, and extract ZIP, TAR, TAR.GZ, TAR.BZ2, TAR.XZ, GZ, BZ2, XZ and 7z
|
||||
• RAR is not supported — it needs native code this app does not ship, and it says so rather
|
||||
than failing with a strange error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user