vincenthz / hs-cryptohash

efficient and practical cryptohashing in haskell. DEPRECATED in favor of cryptonite
Other
30 stars 24 forks source link

md5_do_hash() triggers SIGBUS on SPARC #24

Closed figgles closed 10 years ago

figgles commented 10 years ago

md5_do_hash() triggers a SIGBUS on SPARC.

See https://ghc.haskell.org/trac/ghc/ticket/9002 for the backtrace and the associated Debian Linux bug with my analysis https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=744920

Basically, array_[copy/swap][32/64] can potentially crash on any architecture that requires strict alignment (loading N-byte block requires address aligned to N bytes). This includes SPARC, Itanium, and PowerPC off the top of my head.

Here, using memcpy() will signal to gcc that you aren't sure of the alignment. It will not generate a function to memcpy() for a size of 4/8 bytes. So for example:

void store32(uint32_t* p, uint32_t value) {
    memcpy(p, value, sizeof(value);
}

uint32_t load32(const uint32_t* p) {
    uint32_t v;
    memcpy(&v, p, sizeof(v));
    return v;
}
while( more words to copy) {
    uint32_t tmp = load32(s);
    tmp = swap32(tmp);

    store32(d, tmp);
    s++; d++;
}
vincenthz commented 10 years ago

The best I can think of is that you could write a separate array_swap32 that copy it to destination with memcpy and swap it there for SPARC. The destination is supposed to be always aligned.

figgles commented 10 years ago

Well, it's not just for SPARC, it's most RISC processors in general. The code as you present it here would basically only function 100% of the time on an architecture that silently handles unaligned loads -- e.g. x86. Special casing for SPARC is a band-aid fix.

I still suggest at the very least a load32/64() function. This will have basically 0 effect on x86 but it should resolve the problem for !x86.