Skip to content

Commit c6746a4

Browse files
committed
fixup! Add a function to determine unique prefixes for a list of strings
Let's not walk off the end of the array. Also, avoid an early `malloc()` in `add_prefix_entry()` (avoiding reuse of the same data structure for lookup as for adding a new item), and strengthen the condition for the bug condition. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent f159d0d commit c6746a4

File tree

1 file changed

+25
-27
lines changed

1 file changed

+25
-27
lines changed

prefix-map.c

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,40 +35,40 @@ static void init_prefix_map(struct prefix_map *prefix_map,
3535
static void add_prefix_item(struct prefix_map *prefix_map,
3636
struct prefix_item *item)
3737
{
38-
struct prefix_map_entry *e = xmalloc(sizeof(*e)), *e2;
38+
struct prefix_map_entry e = { { NULL } }, *e2;
3939
int j;
4040

41-
e->item = item;
42-
e->name = e->item->name;
41+
e.item = item;
42+
e.name = item->name;
4343

44-
for (j = prefix_map->min_length; j <= prefix_map->max_length; j++) {
45-
if (!isascii(e->name[j])) {
46-
free(e);
44+
for (j = prefix_map->min_length;
45+
j <= prefix_map->max_length && e.name[j]; j++) {
46+
/* Avoid breaking UTF-8 multi-byte sequences */
47+
if (!isascii(e.name[j]))
4748
break;
48-
}
4949

50-
e->prefix_length = j;
51-
hashmap_entry_init(e, memhash(e->name, j));
52-
e2 = hashmap_get(&prefix_map->map, e, NULL);
50+
e.prefix_length = j;
51+
hashmap_entry_init(&e, memhash(e.name, j));
52+
e2 = hashmap_get(&prefix_map->map, &e, NULL);
5353
if (!e2) {
54-
/* prefix is unique so far */
55-
e->item->prefix_length = j;
56-
hashmap_add(&prefix_map->map, e);
54+
/* prefix is unique at this stage */
55+
item->prefix_length = j;
56+
add_prefix_entry(&prefix_map->map, e.name, j, item);
5757
break;
5858
}
5959

6060
if (!e2->item)
6161
continue; /* non-unique prefix */
6262

63-
if (j != e2->item->prefix_length)
64-
BUG("unexpected prefix length: %d != %d",
65-
(int)j, (int)e2->item->prefix_length);
63+
if (j != e2->item->prefix_length || memcmp(e.name, e2->name, j))
64+
BUG("unexpected prefix length: %d != %d (%s != %s)",
65+
j, (int)e2->item->prefix_length, e.name, e2->name);
6666

6767
/* skip common prefix */
68-
for (; j < prefix_map->max_length && e->name[j]; j++) {
69-
if (e->item->name[j] != e2->item->name[j])
68+
for (; j < prefix_map->max_length && e.name[j]; j++) {
69+
if (e.item->name[j] != e2->item->name[j])
7070
break;
71-
add_prefix_entry(&prefix_map->map, e->name, j + 1,
71+
add_prefix_entry(&prefix_map->map, e.name, j + 1,
7272
NULL);
7373
}
7474

@@ -83,16 +83,14 @@ static void add_prefix_item(struct prefix_map *prefix_map,
8383
e2->item->prefix_length = 0;
8484
e2->item = NULL;
8585

86-
if (j < prefix_map->max_length && e->name[j]) {
86+
if (j < prefix_map->max_length && e.name[j]) {
8787
/* found a unique prefix for the item */
88-
e->item->prefix_length = j + 1;
89-
add_prefix_entry(&prefix_map->map, e->name, j + 1,
90-
e->item);
91-
} else {
88+
e.item->prefix_length = j + 1;
89+
add_prefix_entry(&prefix_map->map, e.name, j + 1,
90+
e.item);
91+
} else
9292
/* item has no (short enough) unique prefix */
93-
e->item->prefix_length = 0;
94-
free(e);
95-
}
93+
e.item->prefix_length = 0;
9694

9795
break;
9896
}

0 commit comments

Comments
 (0)