fix: keep a member hash out of the archive alias

This commit is contained in:
Abdessamad Derraz committed 2026-09-07 04:34:12 +02:00
1 parent 2a4dd59bb2
commit 210ff2b647
2 files changed
+45

No files matched your search

+9
View File
@@ -437,6 +437,15 @@ def _collect_all_aliases(files: dict) -> dict:
sha1 = file_entry.get("sha1", "")
md5 = file_entry.get("md5", "")
# A zipped_file entry verifies a ROM INSIDE the
# archive, so its hash describes the member and not
# the file the name designates. Registering the name
# against that hash made d2fdc.zip an alias of a
# loose 256-byte state-machine-16.rom, which three
# platforms were then served in place of the archive.
if file_entry.get("zipped_file"):
continue
matched = None
if sha1 and sha1 in files:
matched = sha1
+36
View File
@@ -17,6 +17,8 @@ from __future__ import annotations
import hashlib
import json
import os
import re
import sys
import unittest
import zipfile
@@ -182,5 +184,39 @@ class ProfileContradictionsAreKnown(unittest.TestCase):
)
class ArchiveNamesDesignateArchives(unittest.TestCase):
"""A name ending in .zip must not designate a loose file.
The alias collector matched a platform entry's name against the SHA1 its
md5 pointed at without looking at zipped_file, and a zipped_file md5 is
the member's, not the container's. d2fdc.zip became an alias of a loose
256-byte state-machine-16.rom, and three platforms were served that ROM
where they had asked for the archive.
"""
def test_no_archive_name_resolves_to_a_loose_file(self):
database = ROOT / "database.json"
if not database.is_file():
self.skipTest("database.json not built")
db = common.load_database(str(database))
loose = []
for name, ids in db["indexes"]["by_name"].items():
if not name.lower().endswith(".zip"):
continue
for sha1 in ids:
path = db["files"].get(sha1, {}).get("path", "")
base = os.path.basename(path).lower()
# <name>.zip, or the repo's variant form <name>.zip.<md5prefix>
if not re.match(r".*\.zip(\.[0-9a-f]{6,})?$", base):
loose.append(f"{name} -> {path}")
self.assertLessEqual(
len(loose),
1,
"an archive name designates a loose file; the only accepted case is "
"ngpc.zip, whose md5 RetroDECK itself declares against the loose "
f"Neo Geo Pocket Color BIOS:\n " + "\n ".join(sorted(loose)),
)
if __name__ == "__main__":
unittest.main()