Closed thedrow closed 8 years ago
I just checked and it seems that the same bug occurs in hashids-python.
The ruby implementation behaves correctly differently, producing another hash.
6mh9F9i8A9 which is similar until 6mh9F.
Seems like you decode the hash correctly but you cannot encode it so hashids-python considers it invalid.
The problem seems to be that number /= hashids->alphabet_length;
truncates to 0 instead of 1 because in C the division is rounded down with integers. See http://stackoverflow.com/questions/3602827/what-is-the-behavior-of-integer-division-in-c
The solution is to change the hashing loop to:
number = (unsigned long long) floor((float)number / (float)hashids->alphabet_length);
in order to match the Python behaviour. I don't know if that is the correct behaviour though.
Now other hashes fail:
#3: hashids_encode() buffer AOo9QGAVVNYGO does not match expected hash AOo9Ql5nQR1VO
#3: hashids_decode() decoding error
#11: hashids_encode() buffer p2xkL3CK33JjcrrZ8vsw4YRZueZXnk does not match expected hash p2xkL3CK33JjcrrZ8vsw4YRZueZX9k
#11: hashids_decode() decoding error
But when I use double I get less failures:
/Users/omer.katz/Library/Caches/CLion2016.2/cmake/generated/hashids_c-a03af482/a03af482/Debug/unittest
..FF..............
#3: hashids_encode() buffer AOo9Ql5nQRmqO does not match expected hash AOo9Ql5nQR1VO
#3: hashids_decode() decoding error
17 samples, 2 failures
Process finished with exit code 1
According to this I might have stumbled on a compiler bug? http://stackoverflow.com/questions/16716957/convert-unsigned-long-long-to-double-in-c
Nope. We need to use long double
with floorl()
since that's the function for flooring long doubles. I'm pushing the fix right now.
I've just merged your commits with a few more changes I did.
I don't think we need to use floorl()
in the divisions, since integer division suffices the needed results - and I have actually missed to add a strcmp()
in the test cases back in the day :|
I did a few other tweaks as well.
Keep in mind, that encoding huge values (like hex 507f1f77bcf86cd799439011
) is not possible - the limit is 64 bits :-(
I checked and we do have to use floorl(). Otherwise the algorithm fails.
@tzvetkoff Can you explain why the tests now pass?
I have written python bindings to this library and found a bug in encoding.
My first indication was that hashids-python tests were failing:
I added a check to verify that the expected hash matches the encoded hash and there is one test failure.
@tzvetkoff Do you mind helping me fix it?