# HG changeset patch # User Paul Eggert # Date 1368998765 25200 # Node ID 020c917cba9df41e1b056d1a81e37b8525587049 # Parent b876bfd31d0fe7c2639aec655607c926da7a6d03 regex: fix dfa race in multithreaded uses Problem reported by Ludovic Courtès in . * lib/regex_internal.h (lock_define, lock_init, lock_fini): New macros. All uses of __libc_lock_define, __libc_lock_init changed to use the first two of these. (__libc_lock_lock, __libc_lock_unlock): New macros, for non-glibc platforms. (struct re_dfa_t): Define the lock unconditionally. * lib/regexec.c (regexec, re_search_stub): Remove some now-incorrect '#ifdef _LIBC"s. * modules/regex (Depends-on): Add pthread, if we use the included regex. * lib/regcomp.c: Do actions that are not needed for glibc, but may be needed elsewhere. (regfree, re_compile_internal): Destroy the lock. (re_compile_internal): Check for lock-initialization failure. diff -r b876bfd31d0f -r 020c917cba9d ChangeLog --- a/ChangeLog Sun May 19 12:58:53 2013 -0700 +++ b/ChangeLog Sun May 19 14:26:05 2013 -0700 @@ -1,5 +1,24 @@ 2013-05-19 Paul Eggert + regex: fix dfa race in multithreaded uses + Problem reported by Ludovic Courtès in + . + * lib/regex_internal.h (lock_define, lock_init, lock_fini): + New macros. All uses of __libc_lock_define, __libc_lock_init + changed to use the first two of these. + (__libc_lock_lock, __libc_lock_unlock): New macros, for + non-glibc platforms. + (struct re_dfa_t): Define the lock unconditionally. + * lib/regexec.c (regexec, re_search_stub): Remove some now-incorrect + '#ifdef _LIBC"s. + * modules/regex (Depends-on): Add pthread, if we use the + included regex. + + * lib/regcomp.c: Do actions that are not needed for glibc, + but may be needed elsewhere. + (regfree, re_compile_internal): Destroy the lock. + (re_compile_internal): Check for lock-initialization failure. + malloca: port to compilers that reject size-zero arrays This fixes a bug introduced in my previous patch. * lib/malloca.c (struct preliminary_header): Use an int diff -r b876bfd31d0f -r 020c917cba9d lib/regcomp.c --- a/lib/regcomp.c Sun May 19 12:58:53 2013 -0700 +++ b/lib/regcomp.c Sun May 19 14:26:05 2013 -0700 @@ -663,7 +663,10 @@ { re_dfa_t *dfa = preg->buffer; if (BE (dfa != NULL, 1)) - free_dfa_content (dfa); + { + lock_fini (dfa->lock); + free_dfa_content (dfa); + } preg->buffer = NULL; preg->allocated = 0; @@ -784,6 +787,8 @@ preg->used = sizeof (re_dfa_t); err = init_dfa (dfa, length); + if (BE (err == REG_NOERROR && lock_init (dfa->lock) != 0, 0)) + err = REG_ESPACE; if (BE (err != REG_NOERROR, 0)) { free_dfa_content (dfa); @@ -797,8 +802,6 @@ strncpy (dfa->re_str, pattern, length + 1); #endif - __libc_lock_init (dfa->lock); - err = re_string_construct (®exp, pattern, length, preg->translate, (syntax & RE_ICASE) != 0, dfa); if (BE (err != REG_NOERROR, 0)) @@ -806,6 +809,7 @@ re_compile_internal_free_return: free_workarea_compile (preg); re_string_destruct (®exp); + lock_fini (dfa->lock); free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; @@ -838,6 +842,7 @@ if (BE (err != REG_NOERROR, 0)) { + lock_fini (dfa->lock); free_dfa_content (dfa); preg->buffer = NULL; preg->allocated = 0; diff -r b876bfd31d0f -r 020c917cba9d lib/regex_internal.h --- a/lib/regex_internal.h Sun May 19 12:58:53 2013 -0700 +++ b/lib/regex_internal.h Sun May 19 14:26:05 2013 -0700 @@ -32,12 +32,25 @@ #include #include #include + #if defined _LIBC # include +#endif +/* Use __libc_lock_define (, NAME) if the library defines the macro, + and if the compiler is known to support empty macro arguments. */ +#if (defined __libc_lock_define \ + && ((defined __GNUC__ && !defined __STRICT_ANSI__) \ + || (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__))) +# define lock_define(name) __libc_lock_define (, name) +# define lock_init(lock) (__libc_lock_init (lock), 0) +# define lock_fini(lock) 0 #else -# define __libc_lock_init(NAME) do { } while (0) -# define __libc_lock_lock(NAME) do { } while (0) -# define __libc_lock_unlock(NAME) do { } while (0) +# include +# define lock_define(name) pthread_mutex_t name; +# define lock_init(lock) pthread_mutex_init (&(lock), 0) +# define lock_fini(lock) pthread_mutex_destroy (&(lock)) +# define __libc_lock_lock(lock) pthread_mutex_lock (&(lock)) +# define __libc_lock_unlock(lock) pthread_mutex_unlock (&(lock)) #endif /* In case that the system doesn't have isblank(). */ @@ -698,9 +711,7 @@ #ifdef DEBUG char* re_str; #endif -#ifdef _LIBC - __libc_lock_define (, lock) -#endif + lock_define (lock) }; #define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) diff -r b876bfd31d0f -r 020c917cba9d lib/regexec.c --- a/lib/regexec.c Sun May 19 12:58:53 2013 -0700 +++ b/lib/regexec.c Sun May 19 14:26:05 2013 -0700 @@ -228,9 +228,7 @@ { reg_errcode_t err; Idx start, length; -#ifdef _LIBC re_dfa_t *dfa = preg->buffer; -#endif if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) return REG_BADPAT; @@ -421,9 +419,7 @@ Idx nregs; regoff_t rval; int eflags = 0; -#ifdef _LIBC re_dfa_t *dfa = bufp->buffer; -#endif Idx last_start = start + range; /* Check for out-of-range. */ diff -r b876bfd31d0f -r 020c917cba9d modules/regex --- a/modules/regex Sun May 19 12:58:53 2013 -0700 +++ b/modules/regex Sun May 19 14:26:05 2013 -0700 @@ -24,6 +24,7 @@ mbrtowc [test $ac_use_included_regex = yes] mbsinit [test $ac_use_included_regex = yes] nl_langinfo [test $ac_use_included_regex = yes] +pthread [test $ac_use_included_regex = yes] stdbool [test $ac_use_included_regex = yes] stdint [test $ac_use_included_regex = yes] wchar [test $ac_use_included_regex = yes]