Git fork

Merge branch 'rs/oidtree-alignment-fix'

Codepath to access recently added oidtree data structure had
to make unaligned accesses to oids, which has been corrected.

* rs/oidtree-alignment-fix:
oidtree: avoid unaligned access to crit-bit tree

+17 -7
+1 -1
cbtree.h
··· 25 25 */ 26 26 uint32_t byte; 27 27 uint8_t otherbits; 28 - uint8_t k[FLEX_ARRAY]; /* arbitrary data */ 28 + uint8_t k[FLEX_ARRAY]; /* arbitrary data, unaligned */ 29 29 }; 30 30 31 31 struct cb_tree {
+1 -1
hash.h
··· 115 115 116 116 struct object_id { 117 117 unsigned char hash[GIT_MAX_RAWSZ]; 118 - int algo; 118 + int algo; /* XXX requires 4-byte alignment */ 119 119 }; 120 120 121 121 /* A suitably aligned type for stack allocations of hash contexts. */
+15 -5
oidtree.c
··· 31 31 void oidtree_insert(struct oidtree *ot, const struct object_id *oid) 32 32 { 33 33 struct cb_node *on; 34 + struct object_id k; 34 35 35 36 if (!oid->algo) 36 37 BUG("oidtree_insert requires oid->algo"); 37 38 38 39 on = mem_pool_alloc(&ot->mem_pool, sizeof(*on) + sizeof(*oid)); 39 - oidcpy_with_padding((struct object_id *)on->k, oid); 40 + 41 + /* 42 + * Clear the padding and copy the result in separate steps to 43 + * respect the 4-byte alignment needed by struct object_id. 44 + */ 45 + oidcpy_with_padding(&k, oid); 46 + memcpy(on->k, &k, sizeof(k)); 40 47 41 48 /* 42 49 * n.b. Current callers won't get us duplicates, here. If a ··· 68 75 static enum cb_next iter(struct cb_node *n, void *arg) 69 76 { 70 77 struct oidtree_iter_data *x = arg; 71 - const struct object_id *oid = (const struct object_id *)n->k; 78 + struct object_id k; 72 79 73 - if (x->algo != GIT_HASH_UNKNOWN && x->algo != oid->algo) 80 + /* Copy to provide 4-byte alignment needed by struct object_id. */ 81 + memcpy(&k, n->k, sizeof(k)); 82 + 83 + if (x->algo != GIT_HASH_UNKNOWN && x->algo != k.algo) 74 84 return CB_CONTINUE; 75 85 76 86 if (x->last_nibble_at) { 77 - if ((oid->hash[*x->last_nibble_at] ^ x->last_byte) & 0xf0) 87 + if ((k.hash[*x->last_nibble_at] ^ x->last_byte) & 0xf0) 78 88 return CB_CONTINUE; 79 89 } 80 90 81 - return x->fn(oid, x->arg); 91 + return x->fn(&k, x->arg); 82 92 } 83 93 84 94 void oidtree_each(struct oidtree *ot, const struct object_id *oid,