From f50773a89fb61ee2ab4f74f6c37b256c9a3af433 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Mon, 19 Oct 2026 23:14:47 +0200 Subject: [PATCH] fix: the path step checks the size the code reads The name step refuses a candidate outside the size an entry validates, but the path step returned any hashless file at the tail as path_exact, a proof slots arbitration trusts. A 32 KB cpc6128.rom at ZEsarUX's tail would have been served for its 48 KB composite. No profile hits it today. --- scripts/common.py | 7 ++++++- tests/test_path_suffix.py | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/scripts/common.py b/scripts/common.py index 6c6e2c38..a56c7a3f 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -1346,7 +1346,12 @@ def resolve_local_file( if not os.path.exists(path): continue if not has_strong_hash: - if not adler32_fits(file_entry, path, db): + # A path names the file, the size the code checks still + # bounds it, as on the name step: ZEsarUX's 48 KB + # cpc6128.rom is not cap32's 32 KB one at the same tail. + if not name_match_size_ok( + file_entry, files_db[match_sha1].get("size") + ) or not adler32_fits(file_entry, path, db): continue return path, "path_exact" status = _record_match_status(match_sha1) diff --git a/tests/test_path_suffix.py b/tests/test_path_suffix.py index 450573bd..44029906 100644 --- a/tests/test_path_suffix.py +++ b/tests/test_path_suffix.py @@ -251,5 +251,29 @@ class TestForeignTreesAndSharedTails(unittest.TestCase): self.assertEqual((status, path), ("path_exact", "bios/Other/emucorex/resources/RedumpDatabase.yaml")) +class TestSizeGateOnThePathStep(unittest.TestCase): + """The path step took any file at the tail when no hash was declared, + while the name step already refused one outside the checked size.""" + + def test_a_file_outside_the_checked_size_is_not_path_proof(self): + with tempfile.TemporaryDirectory() as root: + previous = os.getcwd() + os.chdir(root) + self.addCleanup(os.chdir, previous) + rel = "bios/Other/x/cpc/cpc6128.rom" + Path(rel).parent.mkdir(parents=True) + Path(rel).write_bytes(b"x" * 32768) + sha1 = "e" * 40 + db = { + "files": {sha1: {"path": rel, "name": "cpc6128.rom", "md5": "", + "size": 32768, "crc32": "", "sha1": sha1}}, + "indexes": {"by_md5": {}, "by_name": {"cpc6128.rom": [sha1]}, + "by_crc32": {}, "by_path_suffix": {"cpc/cpc6128.rom": [sha1]}}, + } + entry = {"name": "cpc6128.rom", "size": 49152, "validation": ["size"]} + _path, status = resolve_local_file(entry, db, dest_hint="cpc/cpc6128.rom") + self.assertNotEqual(status, "path_exact") + + if __name__ == "__main__": unittest.main()