D070 - The hasher read the digest backwards, from the very first commit
decided ยท 2026-08-19
NidHasher took the first eight digest bytes
little-endian. It should be
big-endian. Every NID this project has ever computed
was wrong.
Why nothing caught it. Every test hashed a name with
an arbitrary suffix and compared the result against its own output. That
is self-consistent, and self-consistent with a wrong byte order. The
decoder was right and the hasher was wrong, and the two never met -
decode_symbol_name's own documentation admitted as much,
saying the choice was "consistent but not independently verified".
What exposed it. Hashing published C library names against a real import table. The right convention matched 66 of 468; every other combination of byte order and suffix placement matched zero. There is no ambiguity in a signal like that.
The invariant that was missing, now a test: a hash
must survive a round trip through the symbol-name encoding.
decode(encode(hash(name))) == hash(name). That needs no
suffix, no real module, and no external reference - it compares the two
halves of this crate against each other, which is exactly what nothing
was doing. encode_nid exists mainly so that test can.
The general lesson, worth more than the fix: a test that compares a component to itself proves only internal consistency. Both halves of a two-sided convention can be individually well-tested and jointly wrong. Where two representations must agree, test the agreement.