regfree frees preg->translate (regcomp.c:629), but if the GNU API was used to initialise the pattern buffer, then translate has not been initialised, so may well contain a bogus value. Fix is to initialise it to NULL in re_compile_internal (say, just after regcomp.c:724), and best workaround I can think of is to make sure that you zero the re_pattern_buffer when allocating it.
In fact, the bug is slightly trickier than I thought: GNU regexs do use the translate field, but allow it to be initialised manually, therefore it need not actually point to malloced memory, so regfree shouldn't be trying to free it when the buffer in question is a GNU regex. The workaround is therefore to zero the translate field before calling regfree if it is not either NULL or a pointer to malloced memory, but I'm not sure what the fix is.
Can you please pick an old copy of regex (one with the texinfo manual in it) from ftp.gnu.org and check how translate is documented? Given the way it works now, I would say that it does need to malloced memory (unless you do the extra effort to NULL the field out before calling regfree). My personal theory is that in olden times free(3) was enough to free a GNU regex. Now it's not anymore and you're forced to call regfree.
The way translate is documented, in the node "Translate Tables", is: "You tell Regex to use a translate table on a given pattern buffer by assigning that table's address to the `translate' field of that buffer. If you don't want Regex to do any translation, put zero into this field." Nothing about malloc.
GNU APIs don't allow translate, fastmap etc. to be initialized manually, they require it. re_compile_pattern initializes only some fields of the structure, others are already supposed to be initialized before by the caller. E.g. info regex on translate says: If you don't want Regex to do any translation, put zero into this field. You'll get weird results if you change the table's contents anytime between compiling the pattern buffer, compiling its fastmap, and matching or searching with the pattern buffer. From this it is clear that you must initialize translate before calling re_compile_pattern, either to NULL, or to a translate table. From the info it is not obvious that a valid translate table must be malloced, but e.g. the old regfree shows that that has been always necessary. void regfree (preg) regex_t *preg; { if (preg->buffer != NULL) free (preg->buffer); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; if (preg->fastmap != NULL) free (preg->fastmap); preg->fastmap = NULL; preg->fastmap_accurate = 0; if (preg->translate != NULL) free (preg->translate); preg->translate = NULL; } The easiest is memset (&re, 0, sizeof (re)); before passing &re to re_compile_pattern (or rely on some other zero initialization) and if you need, set some fields in between.