On 05/06/2011 09:40 PM, Marsh Ray wrote:
On 05/06/2011 08:00 PM, Nick Mathewson wrote:
int mem_neq(const void *m1, const void *m2, size_t n) { const uint8_t *b1 = m1, *b2 = m2; uint8_t diff = 0; while (n--) diff |= *b1++ ^ *b2++; return diff != 0; } #define mem_eq(m1, m2, n) (!mem_neq((m1), (m2),(n)))
Looks good to me.
Spoke too soon.
A little birdie (goes by the name of Skywing) pointed out to me in chat that certain compilers are smart enough to realize that the externally-visible result of the function can only go from 0 to 1 one time. This might enable them to break out of the loop early once that happened.
A workaround may be the 'volatile sledgehammer':
int mem_neq(const void *m1, const void *m2, size_t n) { const uint8_t *b1 = m1, *b2 = m2; uint8_t diff = 0; volatile uint8_t * pdiff = &diff; while (n--) *pdiff |= *b1++ ^ *b2++; return *pdiff != 0; }
or perhaps
int mem_neq(const void *m1, const void *m2, size_t n) { const uint8_t *b1 = m1, *b2 = m2; uint8_t diff = 0; while (n--) { diff |= *(volatile const uint8_t *)b1 ^ *(volatile const uint8_t *)b2; b1++; b2++; } return diff != 0; }
Of course, we could always just compute SHA-256 hashes of each side and then compare those, right? :-)
- Marsh