ewah: support platforms that require aligned reads

The caller may hand us an unaligned buffer (e.g., because it is an mmap of a file with many ewah bitmaps). On some platforms (like SPARC) this can cause a bus error. We can fix it with a combination of get_be32 and moving the data into an aligned buffer (which we would do anyway, but we can move it before fixing the endianness). Signed-off-by: Vicent Marti <tanoku@gmail.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Vicent Marti committed Jan 23, 2014 at 16:27 UTC a201c20b41a2f0725977bcb89a2a66135d776ba2
1 file changed +24 -9
ewah/ewah_io.c
+24 -9
@@ -112,23 +112,38 @@ int ewah_serialize(struct ewah_bitmap *self, int fd)
112
113 int ewah_read_mmap(struct ewah_bitmap *self, void *map, size_t len)
114 {
115 - uint32_t *read32 = map;
116 - eword_t *read64;
117 - size_t i;
115 + uint8_t *ptr = map;
116 +
117 + self->bit_size = get_be32(ptr);
118 + ptr += sizeof(uint32_t);
119 +
120 + self->buffer_size = self->alloc_size = get_be32(ptr);
121 + ptr += sizeof(uint32_t);
122
119 - self->bit_size = ntohl(*read32++);
120 - self->buffer_size = self->alloc_size = ntohl(*read32++);
123 self->buffer = ewah_realloc(self->buffer,
124 self->alloc_size * sizeof(eword_t));
125
126 if (!self->buffer)
127 return -1;
128
127 - for (i = 0, read64 = (void *)read32; i < self->buffer_size; ++i)
128 - self->buffer[i] = ntohll(*read64++);
129 + /*
130 + * Copy the raw data for the bitmap as a whole chunk;
131 + * if we're in a little-endian platform, we'll perform
132 + * the endianness conversion in a separate pass to ensure
133 + * we're loading 8-byte aligned words.
134 + */
135 + memcpy(self->buffer, ptr, self->buffer_size * sizeof(uint64_t));
136 + ptr += self->buffer_size * sizeof(uint64_t);
137 +
138 +#if __BYTE_ORDER != __BIG_ENDIAN
139 + {
140 + size_t i;
141 + for (i = 0; i < self->buffer_size; ++i)
142 + self->buffer[i] = ntohll(self->buffer[i]);
143 + }
144 +#endif
145
130 - read32 = (void *)read64;
131 - self->rlw = self->buffer + ntohl(*read32++);
146 + self->rlw = self->buffer + get_be32(ptr);
147
148 return (3 * 4) + (self->buffer_size * 8);
149 }