Skip to content

Commit ff7865d

Browse files
committed
store: Add fast collision detection for FNV-1a 64-bit hashes
Add size-based collision detection when storing clipboard entries with duplicate hashes. If two entries have the same FNV-1a hash but different sizes, return -EFAULT to indicate a definite hash collision. This is very cheap. With: - Max clips: 1000 - Hash space: 2^64 - Collision probability (birthday paradox): ~2.71 × 10^-14 (about one in forty trillion) ...this is extremely unlikely, but since we can deal with it cheaply, just do it. All documented FNV-1a 64-bit collisions with identical sizes are artificially constructed. No naturally occurring same-size collisions are known. Fixes #252.
1 parent 3ff2fb6 commit ff7865d

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

src/store.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ static int _must_use_ _nonnull_
410410
cs_content_add(struct clip_store *cs, uint64_t hash, const char *content,
411411
enum cs_dupe_policy dupe_policy) {
412412
bool dupe = false;
413+
size_t content_len = strlen(content);
413414

414415
char dir_path[CS_HASH_STR_MAX];
415416
snprintf(dir_path, sizeof(dir_path), PRI_HASH, hash);
@@ -432,6 +433,12 @@ cs_content_add(struct clip_store *cs, uint64_t hash, const char *content,
432433
return negative_errno();
433434
}
434435

436+
if ((size_t)st.st_size != content_len) {
437+
// Extremely unlikely with FNV-1a 64-bit outside of artificial
438+
// scenarios, but never hurts to be careful...
439+
return -EFAULT;
440+
}
441+
435442
size_t link_num = (size_t)st.st_nlink + 1;
436443
char linkpath[PATH_MAX];
437444
snprintf(linkpath, sizeof(linkpath), "%s/%zu", dir_path, link_num);
@@ -451,7 +458,7 @@ cs_content_add(struct clip_store *cs, uint64_t hash, const char *content,
451458
}
452459

453460
const char *cur = content;
454-
size_t remaining = strlen(content);
461+
size_t remaining = content_len;
455462

456463
while (remaining > 0) {
457464
ssize_t written = write(fd, cur, remaining);

0 commit comments

Comments
 (0)