Breaking down an interesting function

Spelunking in Netflix’s Javascript, I found this uncharacteristically large function that has all sorts of interesting fiddly bits. It is called 'F6I' which is an immediately invoked function that returns two functions of its own, neatly wrapped up in an object literal:

'F6I': (function() {
    var C9I = function(l9I, j9I) {
            var p9I = j9I & 0xffff,
                o9I = j9I - p9I;
            return ((o9I * l9I | 0) + (p9I * l9I | 0)) | 0;
        },
        i6I = function(I9I, T9I, G9I) {
            if (Y9I[G9I] !== undefined) {
                return Y9I[G9I];
            }
            var V9I = 0xcc9e2d51,
                P9I = 0x1b873593;
            var Z9I = G9I;
            var e9I = T9I & ~0x3;
            for (var r9I = 0; r9I < e9I; r9I += 4) {
                var B9I = (I9I.charCodeAt(r9I) & 0xff) | ((I9I.charCodeAt(r9I + 1) & 0xff) << 8) | ((I9I.charCodeAt(r9I + 2) & 0xff) << 16) | ((I9I.charCodeAt(r9I + 3) & 0xff) << 24);
                B9I = C9I(B9I, V9I);
                B9I = ((B9I & 0x1ffff) << 15) | (B9I >>> 17);
                B9I = C9I(B9I, P9I);
                Z9I ^= B9I;
                Z9I = ((Z9I & 0x7ffff) << 13) | (Z9I >>> 19);
                Z9I = (Z9I * 5 + 0xe6546b64) | 0;
            }
            B9I = 0;
            switch (T9I % 4) {
                case 3:
                    B9I = (I9I.charCodeAt(e9I + 2) & 0xff) << 16;
                case 2:
                    B9I |= (I9I.charCodeAt(e9I + 1) & 0xff) << 8;
                case 1:
                    B9I |= (I9I.charCodeAt(e9I) & 0xff);
                    B9I = C9I(B9I, V9I);
                    B9I = ((B9I & 0x1ffff) << 15) | (B9I >>> 17);
                    B9I = C9I(B9I, P9I);
                    Z9I ^= B9I;
            }
            Z9I ^= T9I;
            Z9I ^= Z9I >>> 16;
            Z9I = C9I(Z9I, 0x85ebca6b);
            Z9I ^= Z9I >>> 13;
            Z9I = C9I(Z9I, 0xc2b2ae35);
            Z9I ^= Z9I >>> 16;
            Y9I[G9I] = Z9I;
            return Z9I;
        },
        Y9I = {};
    return {
        C9I: C9I,
        i6I: i6I
    };
})(),

The two functions it defines are C9I and i6I. Let’s find out what they do!

i6I (the big one)

i6I takes three arguments, and outputs something after doing all sorts of bitwise manipulations to them. I really don’t feel like manually finding out what all that stuff does manually, so I’ll look at some of its defining characteristics. Here are some interesting hints as to what’s going on:

Those magic numbers could be a good start for identifying what kind of algorithm this is running, so let’s just google one of them and see what comes up.

Looks like everything’s about something called MurmurHash, and a quick look at Wikipedia’s pseudocode confirms it. It’s a perfect match! The Wikipedia page also states that it’s vulnerable to hash collisions, so depending on how it’s used, we might be able to get a DoS attack out of this! Exciting stuff.

C9I (the little one)

This is a super small, five line function that does some fancy bitwise manipulations as well. It’s called from the MurmurHash function, and we can pinpoint what it does based on its proximity to some magic number landmarks. Here’s a snippet where it does something with 0x85ebca6b and 0xc2b2ae35:

Z9I = C9I(Z9I, 0x85ebca6b);
Z9I ^= Z9I >>> 13;
Z9I = C9I(Z9I, 0xc2b2ae35);

And here’s the portion from Wikipedia’s pseudocode that also uses those numbers:

hash ← hash × 0x85ebca6b
hash ← hash XOR (hash >> 13)
hash ← hash × 0xc2b2ae35

It’s a near perfect match! It looks like the small C9I function multiplies its two arguments. But what’s up with all that complexity?