| Short description: fnmatch() fails with MBCS. |
| Author(s): Fedora glibc team <glibc@lists.fedoraproject.org> |
| Origin: PATCH |
| Bug-RHEL: #819430, #826149, #826151 |
| Bug-Upstream: #14185 |
| Upstream status: not-submitted |
| |
| fnmatch() fails when '*' wildcard is applied on the file name |
| containing multi-byte character(s) |
| |
| This needs to be reviewed thoroughly and go upstream with a |
| new test case. |
| |
| diff -Nrup a/posix/fnmatch.c b/posix/fnmatch.c |
| |
| |
| @@ -333,6 +333,7 @@ fnmatch (pattern, string, flags) |
| # if HANDLE_MULTIBYTE |
| if (__builtin_expect (MB_CUR_MAX, 1) != 1) |
| { |
| + const char *orig_pattern = pattern; |
| mbstate_t ps; |
| size_t n; |
| const char *p; |
| @@ -356,10 +357,8 @@ fnmatch (pattern, string, flags) |
| alloca_used); |
| n = mbsrtowcs (wpattern, &p, n + 1, &ps); |
| if (__glibc_unlikely (n == (size_t) -1)) |
| - /* Something wrong. |
| - XXX Do we have to set `errno' to something which mbsrtows hasn't |
| - already done? */ |
| - return -1; |
| + /* Something wrong: Fall back to single byte matching. */ |
| + goto try_singlebyte; |
| if (p) |
| { |
| memset (&ps, '\0', sizeof (ps)); |
| @@ -371,10 +370,8 @@ fnmatch (pattern, string, flags) |
| prepare_wpattern: |
| n = mbsrtowcs (NULL, &pattern, 0, &ps); |
| if (__glibc_unlikely (n == (size_t) -1)) |
| - /* Something wrong. |
| - XXX Do we have to set `errno' to something which mbsrtows hasn't |
| - already done? */ |
| - return -1; |
| + /*Something wrong: Fall back to single byte matching. */ |
| + goto try_singlebyte; |
| if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) |
| { |
| __set_errno (ENOMEM); |
| @@ -401,14 +398,8 @@ fnmatch (pattern, string, flags) |
| alloca_used); |
| n = mbsrtowcs (wstring, &p, n + 1, &ps); |
| if (__glibc_unlikely (n == (size_t) -1)) |
| - { |
| - /* Something wrong. |
| - XXX Do we have to set `errno' to something which |
| - mbsrtows hasn't already done? */ |
| - free_return: |
| - free (wpattern_malloc); |
| - return -1; |
| - } |
| + /* Something wrong: Fall back to single byte matching. */ |
| + goto free_and_try_singlebyte; |
| if (p) |
| { |
| memset (&ps, '\0', sizeof (ps)); |
| @@ -420,10 +411,8 @@ fnmatch (pattern, string, flags) |
| prepare_wstring: |
| n = mbsrtowcs (NULL, &string, 0, &ps); |
| if (__glibc_unlikely (n == (size_t) -1)) |
| - /* Something wrong. |
| - XXX Do we have to set `errno' to something which mbsrtows hasn't |
| - already done? */ |
| - goto free_return; |
| + /* Something wrong: Fall back to singlebyte matching. */ |
| + goto free_and_try_singlebyte; |
| if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) |
| { |
| free (wpattern_malloc); |
| @@ -450,6 +439,10 @@ fnmatch (pattern, string, flags) |
| free (wpattern_malloc); |
| |
| return res; |
| + free_and_try_singlebyte: |
| + free(wpattern_malloc); |
| + try_singlebyte: |
| + pattern = orig_pattern; |
| } |
| # endif /* mbstate_t and mbsrtowcs or _LIBC. */ |
| |