Bug Report
On current main (f20b7061), ResolvePathFromKey() is not collision-safe for file-per-key storage.
The path uses only the low 8 bits of std::hash<std::string> for its two directory levels, while SanitizeKey() maps each of /\\:*?"<>| to _. For a fixed tenant, the 10,000 four-character keys built from those characters plus _ all sanitize to the same filename but have only 256 possible directory pairs, so at least two distinct keys must map to the same path.
This is a correctness problem because:
- writes open the destination with
O_TRUNC, so the later key overwrites the earlier file;
StorageBackendAdaptor::BatchLoad() deserializes the stored KVEntry without checking that its key matches the requested key;
- when the colliding keys and values have equal lengths, a read can silently return the other key's value.
The same path helper is used by file-per-key LOCAL_DISK storage and the legacy DISK replica path.
Expected behavior
Distinct object identities must never resolve to the same on-disk object path in normal operation, and reads must reject records whose stored key does not match the requested key.
Proposed direction
Use a stable full-key digest for the filename, retain a legacy-path read fallback for existing files, and validate the deserialized key before copying data to the caller.
Before submitting...
Bug Report
On current
main(f20b7061),ResolvePathFromKey()is not collision-safe for file-per-key storage.The path uses only the low 8 bits of
std::hash<std::string>for its two directory levels, whileSanitizeKey()maps each of/\\:*?"<>|to_. For a fixed tenant, the 10,000 four-character keys built from those characters plus_all sanitize to the same filename but have only 256 possible directory pairs, so at least two distinct keys must map to the same path.This is a correctness problem because:
O_TRUNC, so the later key overwrites the earlier file;StorageBackendAdaptor::BatchLoad()deserializes the storedKVEntrywithout checking that its key matches the requested key;The same path helper is used by file-per-key LOCAL_DISK storage and the legacy DISK replica path.
Expected behavior
Distinct object identities must never resolve to the same on-disk object path in normal operation, and reads must reject records whose stored key does not match the requested key.
Proposed direction
Use a stable full-key digest for the filename, retain a legacy-path read fallback for existing files, and validate the deserialized key before copying data to the caller.
Before submitting...