fix: check size and adler32 on data directory hits

A data directory copy found by name was returned without the size and
Adler-32 checks the name steps over bios/ apply. The verdict now runs
both, for the cache walk, the foreign-tree fallback and release assets.
This commit is contained in:
Abdessamad Derraz committed 2026-10-17 18:20:49 +02:00
1 parent 5a3d9bdc9d
commit 425a0de0e5
3 files changed
+44 -1

No files matched your search

+13 -1
View File
@@ -620,14 +620,22 @@ def declared_hash_verdict(
crc_candidates: set,
zipped_file: str | None,
declared_size,
file_entry: dict | None = None,
db: dict | None = None,
) -> str:
"""Judge a candidate found by name against everything the entry declares.
A file reached through a directory walk was matched on its filename,
which is the weakest evidence there is. Whatever the entry declares
about its content is checked here before the walk may return it.
about its content is checked here before the walk may return it,
including the size and Adler-32 the name steps over bios/ apply.
"""
if not has_strong_hash:
if file_entry is not None and not (
name_match_size_ok(file_entry, os.path.getsize(candidate))
and adler32_fits(file_entry, candidate, db)
):
return "hash_mismatch"
return "data_dir"
algorithms: set[str] = set()
if sha1_candidates:
@@ -1236,6 +1244,8 @@ def resolve_local_file(
crc_candidates=set(),
zipped_file=zipped_file,
declared_size=declared_size,
file_entry=file_entry,
db=db,
),
)
if hit:
@@ -1358,6 +1368,8 @@ def resolve_local_file(
crc_candidates=set(crc_candidates),
zipped_file=zipped_file,
declared_size=declared_size,
file_entry=file_entry,
db=db,
)
hit, data_dir_mismatch = _resolve_in_data_dirs(
names_to_try, data_dir_registry, verdict
+1
View File
@@ -74,6 +74,7 @@ def _verified_asset(
crc_candidates=set(declared["crc32"]),
zipped_file=file_entry.get("zipped_file"),
declared_size=file_entry.get("size"),
file_entry=file_entry,
)
if verdict != "hash_mismatch":
return cached
+30
View File
@@ -2906,3 +2906,33 @@ class AnAcceptedVersionIsNoCoreDiscrepancy(unittest.TestCase):
def test_the_pack_consults_the_alternatives(self):
source = (ROOT / "scripts" / "generate_pack.py").read_text()
self.assertRegex(source, r'status == "hash_mismatch" and not _matches_an_alternative\(')
class ADataDirectoryCopyPassesTheNameChecks(unittest.TestCase):
"""The name steps over bios/ refuse a candidate outside the size or the
Adler-32 the entry's code checks; a cache copy found by the same name
was returned without either check."""
def setUp(self):
self.tmp = Path(tempfile.mkdtemp(dir=TMP_ROOT))
self.addCleanup(lambda: __import__("shutil").rmtree(self.tmp, True))
cache = self.tmp / "cache"
cache.mkdir()
(cache / "wiitdb-pt.txt").write_bytes(b"12345")
self.registry = {"dolphin-sys": {"local_cache": str(cache)}}
self.db = {"files": {}, "indexes": {"by_name": {}, "by_md5": {},
"by_path_suffix": {}, "by_crc32": {}}}
def resolve(self, **fields):
entry = {"name": "wiitdb-pt.txt", **fields}
return resolve_local_file(entry, self.db, data_dir_registry=self.registry)
def test_a_size_the_code_accepts_resolves(self):
self.assertEqual(self.resolve(size=5, validation=["size"])[1], "data_dir")
def test_another_size_is_a_contradiction(self):
self.assertEqual(self.resolve(size=1, validation=["size"])[1], "hash_mismatch")
def test_another_adler32_is_a_contradiction(self):
status = self.resolve(validation=["adler32"], known_hash_adler32="0xdeadbeef")[1]
self.assertEqual(status, "hash_mismatch")