Package: python3-apt
Version: 3.0.0
Severity: important
X-Debbugs-Cc: [email protected]

Dear Maintainer,

`apt.package._file_is_same()` always returns `False` even when the cached
`.deb` file is present and correct. This causes every call to
`Version.fetch_binary()` to re-download the package from the network,
bypassing the destination-path cache entirely.

**Root cause**

Two bugs in `apt/package.py`:

Bug 1 — file opened in text mode:

```python
with open(path) as fobj:          # should be open(path, "rb")
```

Bug 2 — order-sensitive hash comparison:

```python
return apt_pkg.Hashes(fobj).hashes == hashes
```

`HashStringList.__eq__` compares element-by-element (list semantics).
`apt_pkg.Hashes(file)` computes all hash types (MD5, SHA1, SHA256, SHA512),
but the package records only store a subset. The lists differ in both order
and length, so `==` always returns `False`.

**Reproduction**

```python
import apt, apt_pkg, tempfile
from apt.package import _file_is_same

cache = apt.Cache(memonly=True)
version = cache["hello"].candidate
with tempfile.TemporaryDirectory() as tmpdir:
    path = version.fetch_binary(tmpdir)
    print(_file_is_same(path, version.size, version._records.hashes))
    # prints: False  (expected: True)
```

**Fix**

```python
def _file_is_same(path: str, size: int, hashes: apt_pkg.HashStringList) -> bool:
    """Return ``True`` if the file is the same."""
    if os.path.exists(path) and os.path.getsize(path) == size:
        with open(path, "rb") as fobj:
            file_set = {str(h) for h in apt_pkg.Hashes(fobj).hashes}
            return {str(h) for h in hashes} <= file_set
    return False
```

A patch is attached.

-- System Information:
Debian Release: 13.3
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 6.8.0-101-generic (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE
Locale: LANG=C, LC_CTYPE=C.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: unable to detect

Versions of packages python3-apt depends on:
ii  distro-info-data   0.66+deb13u1
ii  libapt-pkg7.0      3.0.3
ii  libc6              2.41-12+deb13u1
ii  libgcc-s1          14.2.0-19
ii  libstdc++6         14.2.0-19
ii  python-apt-common  3.0.0
ii  python3            3.13.5-1

Versions of packages python3-apt recommends:
ii  iso-codes    4.18.0-1
ii  lsb-release  12.1-1

Versions of packages python3-apt suggests:
ii  apt             3.0.3
pn  python-apt-doc  <none>

-- no debconf information

Attachment: 0001-Fix-_file_is_same-to-use-binary-mode-and-subset-hash.patch
Description: application/mbox

Reply via email to