Initial tests confirm the comparisons in your post. There is one small problem I ran into:
exprdump() in mansearch.c:745 accesses the only partially initialized struct expr *e. $ ./apropos Pa=apm/suspend 0000000200 1 0xd0d0d0d0d0d0d0d0 apm/suspend apmd(8/amd64) - Advanced Power Management daemon apmd(8/i386) - Advanced Power Management daemon apmd(8/loongson) - Advanced Power Management daemon apmd(8/macppc) - Advanced Power Management daemon apmd(8/sparc) - Advanced Power Management daemon apmd(8/sparc64) - Advanced Power Management daemon apmd(8/zaurus) - Advanced Power Management daemon $ ./apropos Pa~apm/suspend Bus error This makes testing a bit awkward. The patch below appears to fix this. --- mansearch.c.orig Fri Jul 1 17:26:12 2016 +++ mansearch.c Fri Jul 1 17:28:04 2016 @@ -561,7 +561,7 @@ exprcomp(const struct mansearch *search, int argc, cha continue; } if (parent == NULL) { - parent = mandoc_malloc(sizeof(*parent)); + parent = mandoc_calloc(1, sizeof(*parent)); parent->type = EXPR_OR; parent->next = NULL; parent->child = child; @@ -614,7 +614,7 @@ expr_and(const struct mansearch *search, int argc, cha } needterm = 0; if (parent == NULL) { - parent = mandoc_malloc(sizeof(*parent)); + parent = mandoc_calloc(1, sizeof(*parent)); parent->type = EXPR_AND; parent->next = NULL; parent->child = child; @@ -650,7 +650,7 @@ exprterm(const struct mansearch *search, int argc, cha return e; } - e = mandoc_malloc(sizeof(*e)); + e = mandoc_calloc(1, sizeof(*e)); e->type = EXPR_TERM; e->bits = 0; e->next = NULL;