mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
Fix unnecessary overallocation due to incomplete character
When incomplete characters are found at the end of a string the code ran amok and allocated lots of memory. Stricter limits are now in place.
This commit is contained in:
parent
4f031072a5
commit
8887a920a4
12
ChangeLog
12
ChangeLog
@ -1,5 +1,17 @@
|
|||||||
2011-05-28 Ulrich Drepper <drepper@gmail.com>
|
2011-05-28 Ulrich Drepper <drepper@gmail.com>
|
||||||
|
|
||||||
|
[BZ #12811]
|
||||||
|
* posix/regex_internal.c (build_wcs_buffer): Don't signal we have to
|
||||||
|
grow the buffers more if it already has to be sufficient.
|
||||||
|
(build_wcs_upper_buffer): Likewise.
|
||||||
|
* posix/regexec.c (check_matching): Likewise.
|
||||||
|
(clean_state_log_if_needed): Likewise.
|
||||||
|
(extend_buffers): Don't enlarge buffers beyond size of the input
|
||||||
|
buffer.
|
||||||
|
Patches mostly by Emil Wojak <emil@wojak.eu>.
|
||||||
|
* posix/bug-regex32.c: New file.
|
||||||
|
* posix/Makefile (tests): Add bug-regex32.
|
||||||
|
|
||||||
* locale/findlocale.c (_nl_find_locale): Return right away if
|
* locale/findlocale.c (_nl_find_locale): Return right away if
|
||||||
_nl_explode_name failed.
|
_nl_explode_name failed.
|
||||||
* locale/programs/locarchive.c (add_locale_to_archive): Likewise.
|
* locale/programs/locarchive.c (add_locale_to_archive): Likewise.
|
||||||
|
2
NEWS
2
NEWS
@ -17,7 +17,7 @@ Version 2.14
|
|||||||
12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611, 12625, 12626,
|
12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611, 12625, 12626,
|
||||||
12631, 12650, 12653, 12655, 12660, 12671, 12681, 12685, 12711, 12713,
|
12631, 12650, 12653, 12655, 12660, 12671, 12681, 12685, 12711, 12713,
|
||||||
12714, 12717, 12723, 12724, 12734, 12738, 12746, 12766, 12775, 12777,
|
12714, 12717, 12723, 12724, 12734, 12738, 12746, 12766, 12775, 12777,
|
||||||
12782, 12788, 12792, 12795, 12813, 12814
|
12782, 12788, 12792, 12795, 12811, 12813, 12814
|
||||||
|
|
||||||
* The RPC implementation in libc is obsoleted. Old programs keep working
|
* The RPC implementation in libc is obsoleted. Old programs keep working
|
||||||
but new programs cannot be linked with the routines in libc anymore.
|
but new programs cannot be linked with the routines in libc anymore.
|
||||||
|
@ -82,7 +82,7 @@ tests := tstgetopt testfnm runtests runptests \
|
|||||||
bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
|
bug-regex17 bug-regex18 bug-regex19 bug-regex20 \
|
||||||
bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
|
bug-regex21 bug-regex22 bug-regex23 bug-regex24 \
|
||||||
bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
|
bug-regex25 bug-regex26 bug-regex27 bug-regex28 \
|
||||||
bug-regex29 bug-regex30 bug-regex31 \
|
bug-regex29 bug-regex30 bug-regex31 bug-regex32 \
|
||||||
tst-nice tst-nanosleep tst-regex2 \
|
tst-nice tst-nanosleep tst-regex2 \
|
||||||
transbug tst-rxspencer tst-pcre tst-boost \
|
transbug tst-rxspencer tst-pcre tst-boost \
|
||||||
bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
|
bug-ga1 tst-vfork1 tst-vfork2 tst-vfork3 tst-waitid \
|
||||||
|
36
posix/bug-regex32.c
Normal file
36
posix/bug-regex32.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// BZ 12811
|
||||||
|
#include <regex.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
char buf[1000];
|
||||||
|
regex_t preg;
|
||||||
|
if (setlocale (LC_CTYPE, "de_DE.UTF-8") == NULL)
|
||||||
|
{
|
||||||
|
puts ("setlocale failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int e = regcomp (&preg, ".*ab", REG_ICASE);
|
||||||
|
if (e != 0)
|
||||||
|
{
|
||||||
|
regerror (e, &preg, buf, sizeof (buf));
|
||||||
|
printf ("regcomp = %d \"%s\"\n", e, buf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Incomplete character at the end of the buffer
|
||||||
|
e = regexec (&preg, "aaaaaaaaaaaa\xc4", 0, NULL, 0);
|
||||||
|
|
||||||
|
regfree (&preg);
|
||||||
|
regerror (e, &preg, buf, sizeof (buf));
|
||||||
|
printf ("regexec = %d \"%s\"\n", e, buf);
|
||||||
|
|
||||||
|
return e != REG_NOMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FUNCTION do_test ()
|
||||||
|
#include "../test-skeleton.c"
|
@ -237,13 +237,8 @@ build_wcs_buffer (re_string_t *pstr)
|
|||||||
else
|
else
|
||||||
p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
|
p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
|
||||||
mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
|
mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
|
||||||
if (BE (mbclen == (size_t) -2, 0))
|
if (BE (mbclen == (size_t) -1 || mbclen == 0
|
||||||
{
|
|| (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len), 0))
|
||||||
/* The buffer doesn't have enough space, finish to build. */
|
|
||||||
pstr->cur_state = prev_st;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))
|
|
||||||
{
|
{
|
||||||
/* We treat these cases as a singlebyte character. */
|
/* We treat these cases as a singlebyte character. */
|
||||||
mbclen = 1;
|
mbclen = 1;
|
||||||
@ -252,6 +247,12 @@ build_wcs_buffer (re_string_t *pstr)
|
|||||||
wc = pstr->trans[wc];
|
wc = pstr->trans[wc];
|
||||||
pstr->cur_state = prev_st;
|
pstr->cur_state = prev_st;
|
||||||
}
|
}
|
||||||
|
else if (BE (mbclen == (size_t) -2, 0))
|
||||||
|
{
|
||||||
|
/* The buffer doesn't have enough space, finish to build. */
|
||||||
|
pstr->cur_state = prev_st;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write wide character and padding. */
|
/* Write wide character and padding. */
|
||||||
pstr->wcs[byte_idx++] = wc;
|
pstr->wcs[byte_idx++] = wc;
|
||||||
@ -334,9 +335,11 @@ build_wcs_upper_buffer (re_string_t *pstr)
|
|||||||
for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
|
for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
|
||||||
pstr->wcs[byte_idx++] = WEOF;
|
pstr->wcs[byte_idx++] = WEOF;
|
||||||
}
|
}
|
||||||
else if (mbclen == (size_t) -1 || mbclen == 0)
|
else if (mbclen == (size_t) -1 || mbclen == 0
|
||||||
|
|| (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
|
||||||
{
|
{
|
||||||
/* It is an invalid character or '\0'. Just use the byte. */
|
/* It is an invalid character, an incomplete character
|
||||||
|
at the end of the string, or '\0'. Just use the byte. */
|
||||||
int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
|
int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
|
||||||
pstr->mbs[byte_idx] = ch;
|
pstr->mbs[byte_idx] = ch;
|
||||||
/* And also cast it to wide char. */
|
/* And also cast it to wide char. */
|
||||||
@ -449,7 +452,8 @@ build_wcs_upper_buffer (re_string_t *pstr)
|
|||||||
for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
|
for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
|
||||||
pstr->wcs[byte_idx++] = WEOF;
|
pstr->wcs[byte_idx++] = WEOF;
|
||||||
}
|
}
|
||||||
else if (mbclen == (size_t) -1 || mbclen == 0)
|
else if (mbclen == (size_t) -1 || mbclen == 0
|
||||||
|
|| (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
|
||||||
{
|
{
|
||||||
/* It is an invalid character or '\0'. Just use the byte. */
|
/* It is an invalid character or '\0'. Just use the byte. */
|
||||||
int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
|
int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Extended regular expression matching and search library.
|
/* Extended regular expression matching and search library.
|
||||||
Copyright (C) 2002-2005, 2007, 2009, 2010 Free Software Foundation, Inc.
|
Copyright (C) 2002-2005,2007,2009,2010,2011 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
|
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
|
||||||
|
|
||||||
@ -1156,7 +1156,8 @@ check_matching (re_match_context_t *mctx, int fl_longest_match,
|
|||||||
re_dfastate_t *old_state = cur_state;
|
re_dfastate_t *old_state = cur_state;
|
||||||
int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
|
int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
|
||||||
|
|
||||||
if (BE (next_char_idx >= mctx->input.bufs_len, 0)
|
if ((BE (next_char_idx >= mctx->input.bufs_len, 0)
|
||||||
|
&& mctx->input.bufs_len < mctx->input.len)
|
||||||
|| (BE (next_char_idx >= mctx->input.valid_len, 0)
|
|| (BE (next_char_idx >= mctx->input.valid_len, 0)
|
||||||
&& mctx->input.valid_len < mctx->input.len))
|
&& mctx->input.valid_len < mctx->input.len))
|
||||||
{
|
{
|
||||||
@ -1732,7 +1733,8 @@ clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
|
|||||||
{
|
{
|
||||||
int top = mctx->state_log_top;
|
int top = mctx->state_log_top;
|
||||||
|
|
||||||
if (next_state_log_idx >= mctx->input.bufs_len
|
if ((next_state_log_idx >= mctx->input.bufs_len
|
||||||
|
&& mctx->input.bufs_len < mctx->input.len)
|
||||||
|| (next_state_log_idx >= mctx->input.valid_len
|
|| (next_state_log_idx >= mctx->input.valid_len
|
||||||
&& mctx->input.valid_len < mctx->input.len))
|
&& mctx->input.valid_len < mctx->input.len))
|
||||||
{
|
{
|
||||||
@ -4111,7 +4113,7 @@ extend_buffers (re_match_context_t *mctx)
|
|||||||
return REG_ESPACE;
|
return REG_ESPACE;
|
||||||
|
|
||||||
/* Double the lengthes of the buffers. */
|
/* Double the lengthes of the buffers. */
|
||||||
ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
|
ret = re_string_realloc_buffers (pstr, MIN (pstr->len, pstr->bufs_len * 2));
|
||||||
if (BE (ret != REG_NOERROR, 0))
|
if (BE (ret != REG_NOERROR, 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user