Package: depthcharge-tools
Version: 0.6.2-5
Tags: patch upstream
Control: found -1 0.6.1-1
X-Debbugs-CC: [email protected]

If the lzma package is installed, "depthchargectl build" fails:

  $ depthchargectl build --board amd64-generic -vvv
  [...]
  Failed while creating depthcharge image.
  Traceback (most recent call last):
    File 
"/usr/lib/python3/dist-packages/depthcharge_tools/depthchargectl/_build.py", 
line 558, in __call__
      mkdepthcharge(
      ~~~~~~~~~~~~~^
          arch=self.board.arch,
          ^^^^^^^^^^^^^^^^^^^^^
      ...<12 lines>...
          verbosity=self.verbosity,
          ^^^^^^^^^^^^^^^^^^^^^^^^^
      )
      ^
    File "/usr/lib/python3/dist-packages/depthcharge_tools/utils/argparse.py", 
line 863, in __normal_call
      retval = inst(*args, **kwargs)
    File "/usr/lib/python3/dist-packages/depthcharge_tools/utils/argparse.py", 
line 799, in __call__
      return call(self)
    File "/usr/lib/python3/dist-packages/depthcharge_tools/mkdepthcharge.py", 
line 960, in __call__
      with vmlinuz.open("r+b") as f, mmap(f.fileno(), 0) as data:
                                     ~~~~^^^^^^^^^^^^^^^
  ValueError: cannot mmap an empty file
  [...]

The reason is that d-t tries decompressing with available programs to see
if the file is compressed, and "lzma -dc /boot/vmlinuz-$(uname -r)"
returns empty output with exit status zero even though the file isn't
compressed by lzma. So we end up trying to process the empty output as
the kernel binary.

Regardless of if the lzma behaviour is a bug, we should check against
this successful-but-empty decompression result when checking if files
are compressed to avoid this.

Luckily lzma isn't automatically installed along with kernel or
initramfs-tools etc., and depthcharge-tools depends on xz-utils which
provides lzma anyway, so I guess it wouldn't be installed except if
installed explicitly (as I did for testing).

Attaching patch I'm planning to commit upstream.


-- System Information:
Debian Release: forky/sid
  APT prefers buildd-unstable
  APT policy: (500, 'buildd-unstable'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: arm64, armhf, i386

Kernel: Linux 7.1.8+deb14.1-amd64 (SMP w/8 CPU threads; PREEMPT)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_GB:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages depthcharge-tools depends on:
ii  cgpt                  0~R106-15054.B+dfsg-0.1
ii  device-tree-compiler  1.7.2-2+b3
ii  linux-base            4.16
ii  lz4                   1.10.0-10
ii  python3               3.13.9-3+b1
ii  python3-packaging     26.2-2
ii  u-boot-tools          2025.01-3.2
ii  vboot-kernel-utils    0~R106-15054.B+dfsg-0.1
ii  vboot-utils           0~R106-15054.B+dfsg-0.1
ii  xz-utils              5.8.3-1

depthcharge-tools recommends no packages.

Versions of packages depthcharge-tools suggests:
ii  bzip2  1.0.8-6+b2
ii  lzop   1.04-2
ii  zstd   1.5.7+dfsg-4

-- no debconf information
From 7d44744fc224b06ee37487de22f9f36608a5f5e3 Mon Sep 17 00:00:00 2001
From: Alper Nebi Yasak <[email protected]>
Date: Thu, 9 Jul 2026 11:25:06 +0300
Subject: [PATCH] utils: pathlib: Avoid returning empty decompression output

We try to decompress input files with the usual compression tools to use
the decompressed versions which would be the actual bootable artifacts.
If the lzma Debian package is installed, that one provides the lzma
compressor instead of the xz-utils package, and causes `depthchargectl
build` to fail with an error:

  $ depthchargectl build --board amd64-generic -vvv
  [...]
  Failed while creating depthcharge image.
  Traceback (most recent call last):
  [...]
  File "/usr/lib/python3/dist-packages/depthcharge_tools/mkdepthcharge.py", line 960, in __call__
    with vmlinuz.open("r+b") as f, mmap(f.fileno(), 0) as data:
                                   ~~~~^^^^^^^^^^^^^^^
  ValueError: cannot mmap an empty file
  [...]

Ultimately, it's because `lzma -d` returns a zero exit status for certain
files even though it outputs nothing:

  $ head -c18 "/boot/vmlinuz-$(uname -a)" | xxd
  00000000: 4d5a 0000 0000 0000 0000 0000 0000 0000  MZ..............
  00000010: 0000                                     ..

  $ head -c18 "/boot/vmlinuz-$(uname -a)" | lzma -d; echo $?
  0

Check against empty decompression outputs, consider them not compressed
with that scheme, and so continue trying with other decompressors.
We need to remove the newly created empty file so the next compressor
doesn't throw up a FileExistsError.

Signed-off-by: Alper Nebi Yasak <[email protected]>
---
 depthcharge_tools/utils/pathlib.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/depthcharge_tools/utils/pathlib.py b/depthcharge_tools/utils/pathlib.py
index 4063312cc8cb..ffb5f7ae918a 100644
--- a/depthcharge_tools/utils/pathlib.py
+++ b/depthcharge_tools/utils/pathlib.py
@@ -31,7 +31,13 @@ def decompress(src, dest=None, partial=False):
 
     for runner in (gzip, zstd, xz, lz4, lzma, bzip2, lzop):
         try:
-            return runner.decompress(src, dest)
+            out = runner.decompress(src, dest)
+            if out in (None, "", b""):
+                continue
+            if isinstance(out, Path) and out.stat().st_size == 0:
+                out.unlink(missing_ok=True)
+                continue
+            return out
 
         except FileNotFoundError:
             if dest:

base-commit: 95d17c444ae3a9dec1c51ead6301ed04777314b9
-- 
2.55.0

Reply via email to