mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-09-20 18:51:26 -03:00
fix(recipes): reject the empty-hash placeholder when resolving LoRA hashes
The SHA256 of an empty byte string (written by repackaging tools into safetensors metadata, or produced by hashing an empty/unreadable file) was previously resolved against CivitAI's by-hash API, which can contain polluted entries for it (e.g. a broken SD 1.5 LoRA whose AutoV3 equals the placeholder) and falsely attributed the wrong model to a recipe. Guard all lookup paths for the 10/12/64-char AutoV2/AutoV3/full-SHA256 spellings: CivitaiClient.get_model_by_hash/_fetch_version_by_hash return not-found without a request, and ModelHashIndex ignores the placeholder in has_hash/get_path/add_autov3. The Automatic1111 metadata parser keeps the LoRA item itself when its hash is the placeholder: it matches by filename locally, or retains the entry with an empty hash flagged hashInvalid (unresolvable-hash state in the UI, with reconnect as the remedy) instead of dropping it or resolving it to a polluted CivitAI entry.
This commit is contained in:
+26
-5
@@ -1,3 +1,5 @@
|
||||
from typing import Any
|
||||
|
||||
NSFW_LEVELS = {
|
||||
"PG": 1,
|
||||
"PG13": 2,
|
||||
@@ -99,11 +101,30 @@ DEFAULT_HASH_CHUNK_SIZE_MB = 4
|
||||
# absurd 64-bit header length from forcing a multi-GB allocation during scan.
|
||||
MAX_SAFETENSORS_HEADER_BYTES = 64 * 1024 * 1024
|
||||
|
||||
# First 12 chars of the SHA256 of an empty byte string. Some (re-packaging)
|
||||
# training tools write this placeholder into safetensors metadata instead of a
|
||||
# real hash; it must never be treated as a valid AutoV3 — several broken
|
||||
# models sharing it would collide in the hash index and falsely match recipes.
|
||||
INVALID_AUTOV3_EMPTY_HASH = "e3b0c44298fc"
|
||||
# SHA256 of an empty byte string. Some (re-packaging) training tools write a
|
||||
# truncated form of this placeholder into safetensors metadata (as
|
||||
# ``modelspec.hash_sha256`` / ``sshs_model_hash``), and hashing an empty or
|
||||
# unreadable file produces it directly. It must never be treated as a valid
|
||||
# hash: several broken models share it, CivitAI's by-hash index can contain
|
||||
# such polluted entries, and matching it falsely attributes recipes.
|
||||
EMPTY_HASH_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
INVALID_AUTOV3_EMPTY_HASH = EMPTY_HASH_SHA256[:12]
|
||||
INVALID_AUTOV2_EMPTY_HASH = EMPTY_HASH_SHA256[:10]
|
||||
|
||||
|
||||
def is_empty_placeholder_hash(value: Any) -> bool:
|
||||
"""True for a 10/12/64-hex-char spelling of the empty-hash placeholder.
|
||||
|
||||
These are the AutoV2, AutoV3 and full-SHA256 forms of the placeholder;
|
||||
such values identify no real model and must never be resolved against
|
||||
local files or CivitAI.
|
||||
"""
|
||||
if not isinstance(value, str):
|
||||
return False
|
||||
v = value.strip().lower()
|
||||
if len(v) not in (10, 12, 64):
|
||||
return False
|
||||
return v == EMPTY_HASH_SHA256[: len(v)]
|
||||
|
||||
# Auto-organize settings
|
||||
AUTO_ORGANIZE_BATCH_SIZE = (
|
||||
|
||||
Reference in New Issue
Block a user