Skip to content

XorBinaryFuse silent failure #49

Description

@vprus

There is code in XorBinaryFuse8

https://github.com/FastFilter/fastfilter_java/blob/master/fastfilter/src/main/java/org/fastfilter/xor/XorBinaryFuse8.java#L201

that appears to silently fail, and fill the fingerprint array with 0xFF.

Then, the code in mayContain goes like this:

byte f = fingerprint(hash)
f ^= fingerprints[h0] ^ fingerprints[h1] ^ fingerprints[h2];
return (f & 0xff) == 0;

that essentially becomes

f ^= 0xFF ^ 0xFF ^ 0xFF
return (f & 0xff) == 0;

or

f ^= 0xFF;
return (f & 0xFF) == 0;

or

return (f == 0xFF)

In other words, mayContain will now return false most inputs, generating false negatives.

I would suggest that this behaviour is catastrophic in practical code, and a better approach would be to modify the code to through an exception.

Activity

  1. lemire commented on Jan 19, 2026

    @lemire
    Member

    @vprus Good point. Would you consider providing a pull request?

  2. lemire commented on Jan 19, 2026

    @lemire
    Member

    @vprus Your blog at https://vladimirprus.com/blog/ seems to be missing an RSS feed.

  3. vprus commented on Jan 19, 2026

    @vprus
    ContributorAuthor

    I have a local patch to add an exception, so yes, can turn that into a PR.

    If you're OK with AI-assisted, but human-checked PRs, I can ask Copilot to review other implementations for the same issue as well, let me know.

  4. vprus commented on Jan 19, 2026

    @vprus
    ContributorAuthor

    Nevermind, there seems to be 3 such places, will provide a PR shortly.

  5. vprus commented on Jan 19, 2026

    @vprus
    ContributorAuthor

    Created #50

  6. lemire commented on Jan 19, 2026

    @lemire
    Member

    Just for context, this path should NEVER happen. If it does, it is a bug. So yeah, generating an exception is a good way to handle it.

  7. vprus commented on Jan 19, 2026

    @vprus
    ContributorAuthor

    I don't really understand the underlying math, but I had around 50K strings, so I assumed that String.hashCode.toLong, while imperfect, should still work. Apparently, it did not, and my naive attempt to rehash it into 64-bit did not help either.

  8. lemire commented on Jan 19, 2026

    @lemire
    Member

    @vprus It is almost certainly the case that you have collisions. The Java implementation is a bit naive, but what we do with the other implementations is to prune the duplicates. I'll create a PR on this topic.

    That should not happen with 50K strings if you have good hashing. But that's not good: String.hashCode.toLong. I think Google's Guava library must have good hash functions.

    So, essentially, it fails because of a bug, and the bug is the use of an excessively weak hashing.

  9. vprus commented on Jan 19, 2026

    @vprus
    ContributorAuthor

    Yes, you are correct. There were two strings with the same hashCode. Using either xxhash or String.hashCode.toLong+distinct worked for me.

    Thanks for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions