mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-13 21:43:55 -06:00
fix: write the cut md5 rule once
Six places read an md5 shorter than 32 digits, each with its own bound. digest_verdict accepted any prefix down to one digit, while Batocera compares the whole string (batocera-systems:1088). A cut value now names a dump only when one held md5 starts with it (cut_md5_owner, read by the scraper, the resolver and --from-md5), and every verdict compares whole digests.
This commit is contained in:
1 parent
8af7b0da13
commit
ed6643022d
10 files changed
+71
-78
No files matched your search
+15
-14
@@ -1434,6 +1434,15 @@ def resolve_local_file(
|
||||
names_to_try.append(hint_base)
|
||||
|
||||
md5_list = parse_md5_list(file_entry.get("md5"))
|
||||
files_db = db.get("files", {})
|
||||
by_md5 = db.get("indexes", {}).get("by_md5", {})
|
||||
# A value cut short stands for the one held md5 it starts, and only
|
||||
# then (cut_md5_owner): the dump it names is still name-guarded below.
|
||||
cut_owners = {
|
||||
cut: owner for cut in md5_list
|
||||
if len(cut) < 32 and (owner := cut_md5_owner(cut, by_md5))
|
||||
}
|
||||
md5_list = [cut_owners.get(value, value) for value in md5_list]
|
||||
sha1_candidates = [
|
||||
str(value).strip().lower()
|
||||
for value in (sha1 if isinstance(sha1, list) else [sha1] if sha1 else [])
|
||||
@@ -1461,8 +1470,6 @@ def resolve_local_file(
|
||||
has_strong_hash = bool(
|
||||
sha1_candidates or sha256_candidates or md5_list or crc_candidates
|
||||
)
|
||||
files_db = db.get("files", {})
|
||||
by_md5 = db.get("indexes", {}).get("by_md5", {})
|
||||
by_name = db.get("indexes", {}).get("by_name", {})
|
||||
by_path_suffix = db.get("indexes", {}).get("by_path_suffix", {})
|
||||
|
||||
@@ -1483,7 +1490,7 @@ def resolve_local_file(
|
||||
# With zipped_file the MD5 identifies the member, not the container.
|
||||
if md5_list and not zipped_file:
|
||||
actual_md5 = str(entry.get("md5", "")).lower()
|
||||
if not any(actual_md5.startswith(expected) for expected in md5_list):
|
||||
if actual_md5 not in md5_list:
|
||||
return None
|
||||
statuses.append("md5_exact")
|
||||
if crc_candidates:
|
||||
@@ -1567,20 +1574,13 @@ def resolve_local_file(
|
||||
sha1_match = by_md5.get(md5_candidate)
|
||||
if sha1_match and sha1_match in files_db:
|
||||
path = files_db[sha1_match]["path"]
|
||||
# Full MD5 (32 chars) is a strong identifier: trust it
|
||||
# without name guard. Truncated MD5 still needs name check
|
||||
# to avoid cross-contamination.
|
||||
# A full md5 as declared is a strong identifier: trusted
|
||||
# without name guard. One completed from a cut value still
|
||||
# needs the name check to avoid cross-contamination.
|
||||
status = _record_match_status(sha1_match)
|
||||
if status and os.path.exists(path):
|
||||
if len(md5_candidate) >= 32 or _md5_name_ok(path):
|
||||
if md5_candidate not in cut_owners.values() or _md5_name_ok(path):
|
||||
return path, status
|
||||
if len(md5_candidate) < 32:
|
||||
for db_md5, db_sha1 in by_md5.items():
|
||||
if db_md5.startswith(md5_candidate) and db_sha1 in files_db:
|
||||
path = files_db[db_sha1]["path"]
|
||||
status = _record_match_status(db_sha1)
|
||||
if status and os.path.exists(path) and _md5_name_ok(path):
|
||||
return path, status
|
||||
|
||||
# 2b. Path suffix lookup is useful for same-named regional files, but it
|
||||
# is identity evidence only when no content hash was declared. A stale
|
||||
@@ -3586,6 +3586,7 @@ from hashing import ( # noqa: E402,F401
|
||||
md5sum,
|
||||
md5_composite,
|
||||
parse_md5_list,
|
||||
cut_md5_owner,
|
||||
_ALL_ALGORITHMS,
|
||||
_md5_composite_cache,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user