[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
fnmatch memory allocation fix
From: |
Bruno Haible |
Subject: |
fnmatch memory allocation fix |
Date: |
Mon, 31 Jul 2006 16:44:23 +0200 |
User-agent: |
KMail/1.9.1 |
Hi,
When trying to use the 'fnmatch' module for GNU gettext, I found thst it
still depends on the old 'alloca' module that relies on an external function
on platforms like HP-UX 10.00 with cc. IMO the better choice is to use
the 'alloca-opt' module and hand-optimized code for modules that come from
glibc, and the 'allocsa' module for higher-level code.
Furthermore fnmatch_loop.c has a gratuitous limit of 2000 characters for
patterns; 2000 is less than PATH_MAX!
Here is a proposed patch to fix both.
2006-07-30 Bruno Haible <address@hidden>
* fnmatch.c (fnmatch): On platforms without alloca, set ALLOCA_LIMIT
to 0, so that the memory allocation always uses malloc.
* fnmatch_loop.c (EXT): Use malloc as alternative to alloca, when
the pattern size is big. On platforms without alloca, set ALLOCA_LIMIT
to 0, so that the memory allocation always uses malloc.
* modules/fnmatch (Depends-on): Add alloca-opt, remove alloca.
*** lib/fnmatch.c.bak 2006-07-11 13:54:17.000000000 +0200
--- lib/fnmatch.c 2006-07-30 20:23:09.000000000 +0200
***************
*** 276,282 ****
fnmatch (const char *pattern, const char *string, int flags)
{
# if HANDLE_MULTIBYTE
! # define ALLOCA_LIMIT 2000
if (__builtin_expect (MB_CUR_MAX, 1) != 1)
{
mbstate_t ps;
--- 276,286 ----
fnmatch (const char *pattern, const char *string, int flags)
{
# if HANDLE_MULTIBYTE
! # if HAVE_ALLOCA || defined _LIBC
! # define ALLOCA_LIMIT 2000
! # else
! # define ALLOCA_LIMIT 0
! # endif
if (__builtin_expect (MB_CUR_MAX, 1) != 1)
{
mbstate_t ps;
*** lib/fnmatch_loop.c.bak 2006-07-11 13:54:17.000000000 +0200
--- lib/fnmatch_loop.c 2006-07-30 21:03:04.000000000 +0200
***************
*** 1003,1022 ****
struct patternlist
{
struct patternlist *next;
CHAR str[1];
} *list = NULL;
struct patternlist **lastp = &list;
size_t pattern_len = STRLEN (pattern);
const CHAR *p;
const CHAR *rs;
enum { ALLOCA_LIMIT = 8000 };
/* Parse the pattern. Store the individual parts in the list. */
level = 0;
for (startp = p = pattern + 1; ; ++p)
if (*p == L_('\0'))
/* This is an invalid pattern. */
! return -1;
else if (*p == L_('['))
{
/* Handle brackets special. */
--- 1003,1028 ----
struct patternlist
{
struct patternlist *next;
+ int malloced;
CHAR str[1];
} *list = NULL;
struct patternlist **lastp = &list;
size_t pattern_len = STRLEN (pattern);
const CHAR *p;
const CHAR *rs;
+ #if HAVE_ALLOCA || defined _LIBC
enum { ALLOCA_LIMIT = 8000 };
+ #else
+ enum { ALLOCA_LIMIT = 0 };
+ #endif
+ int retval;
/* Parse the pattern. Store the individual parts in the list. */
level = 0;
for (startp = p = pattern + 1; ; ++p)
if (*p == L_('\0'))
/* This is an invalid pattern. */
! goto failed;
else if (*p == L_('['))
{
/* Handle brackets special. */
***************
*** 1034,1040 ****
while (*p != L_(']'))
if (*p++ == L_('\0'))
/* This is no valid pattern. */
! return -1;
}
else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
|| *p == L_('!')) && p[1] == L_('('))
--- 1040,1046 ----
while (*p != L_(']'))
if (*p++ == L_('\0'))
/* This is no valid pattern. */
! goto failed;
}
else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@')
|| *p == L_('!')) && p[1] == L_('('))
***************
*** 1057,1067 ****
plensize = plen * sizeof (CHAR); \
newpsize = offsetof (struct patternlist, str) + plensize; \
if ((size_t) -1 / sizeof (CHAR) < plen \
! || newpsize < offsetof (struct patternlist, str) \
! || ALLOCA_LIMIT <= newpsize) \
! return -1; \
! newp = (struct patternlist *) alloca (newpsize); \
! *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \
newp->next = NULL; \
*lastp = newp; \
lastp = &newp->next
--- 1063,1083 ----
plensize = plen * sizeof (CHAR); \
newpsize = offsetof (struct patternlist, str) + plensize; \
if ((size_t) -1 / sizeof (CHAR) < plen \
! || newpsize < offsetof (struct patternlist, str)) \
! goto failed; \
! if (newpsize < ALLOCA_LIMIT) \
! { \
! newp = (struct patternlist *) alloca (newpsize); \
! newp->malloced = 0; \
! } \
! else \
! { \
! newp = (struct patternlist *) malloc (newpsize); \
! if (!newp) \
! goto failed; \
! newp->malloced = 1; \
! } \
! *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \
newp->next = NULL; \
*lastp = newp; \
lastp = &newp->next
***************
*** 1085,1096 ****
{
case L_('*'):
if (FCT (p, string, string_end, no_leading_period, flags) == 0)
! return 0;
/* FALLTHROUGH */
case L_('+'):
do
{
for (rs = string; rs <= string_end; ++rs)
/* First match the prefix with the current pattern with the
current pattern. */
--- 1101,1117 ----
{
case L_('*'):
if (FCT (p, string, string_end, no_leading_period, flags) == 0)
! {
! retval = 0;
! goto done;
! }
/* FALLTHROUGH */
case L_('+'):
do
{
+ struct patternlist *next;
+
for (rs = string; rs <= string_end; ++rs)
/* First match the prefix with the current pattern with the
current pattern. */
***************
*** 1112,1142 ****
: rs[-1] == '/' && NO_LEADING_PERIOD (flags),
flags & FNM_FILE_NAME
? flags : flags & ~FNM_PERIOD) == 0)))
! /* It worked. Signal success. */
! return 0;
}
! while ((list = list->next) != NULL);
/* None of the patterns lead to a match. */
return FNM_NOMATCH;
case L_('?'):
if (FCT (p, string, string_end, no_leading_period, flags) == 0)
! return 0;
/* FALLTHROUGH */
case L_('@'):
do
! /* I cannot believe it but `strcat' is actually acceptable
! here. Match the entire string with the prefix from the
! pattern list and the rest of the pattern following the
! pattern list. */
! if (FCT (STRCAT (list->str, p), string, string_end,
! no_leading_period,
! flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
! /* It worked. Signal success. */
! return 0;
! while ((list = list->next) != NULL);
/* None of the patterns lead to a match. */
return FNM_NOMATCH;
--- 1133,1186 ----
: rs[-1] == '/' && NO_LEADING_PERIOD (flags),
flags & FNM_FILE_NAME
? flags : flags & ~FNM_PERIOD) == 0)))
! {
! /* It worked. Signal success. */
! retval = 0;
! goto done;
! }
!
! next = list->next;
! if (list->malloced)
! free (list);
! list = next;
}
! while (list != NULL);
/* None of the patterns lead to a match. */
return FNM_NOMATCH;
case L_('?'):
if (FCT (p, string, string_end, no_leading_period, flags) == 0)
! {
! retval = 0;
! goto done;
! }
/* FALLTHROUGH */
case L_('@'):
do
! {
! struct patternlist *next;
!
! /* I cannot believe it but `strcat' is actually acceptable
! here. Match the entire string with the prefix from the
! pattern list and the rest of the pattern following the
! pattern list. */
! if (FCT (STRCAT (list->str, p), string, string_end,
! no_leading_period,
! flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0)
! {
! /* It worked. Signal success. */
! retval = 0;
! goto done;
! }
!
! next = list->next;
! if (list->malloced)
! free (list);
! list = next;
! }
! while (list != NULL);
/* None of the patterns lead to a match. */
return FNM_NOMATCH;
***************
*** 1159,1178 ****
: rs[-1] == '/' && NO_LEADING_PERIOD (flags),
flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
== 0))
! /* This is successful. */
! return 0;
}
/* None of the patterns together with the rest of the pattern
lead to a match. */
! return FNM_NOMATCH;
default:
assert (! "Invalid extended matching operator");
break;
}
! return -1;
}
--- 1203,1237 ----
: rs[-1] == '/' && NO_LEADING_PERIOD (flags),
flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD)
== 0))
! {
! /* This is successful. */
! retval = 0;
! goto done;
! }
}
/* None of the patterns together with the rest of the pattern
lead to a match. */
! retval = FNM_NOMATCH;
! goto done;
default:
assert (! "Invalid extended matching operator");
break;
}
! failed:
! retval = -1;
! done:
! while (list != NULL)
! {
! struct patternlist *next = list->next;
!
! if (list->malloced)
! free (list);
! list = next;
! }
! return retval;
}
*** modules/fnmatch.bak 2005-07-23 00:04:12.000000000 +0200
--- modules/fnmatch 2006-07-30 20:44:18.000000000 +0200
***************
*** 9,15 ****
m4/fnmatch.m4
Depends-on:
! alloca
stdbool
configure.ac:
--- 9,15 ----
m4/fnmatch.m4
Depends-on:
! alloca-opt
stdbool
configure.ac:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- fnmatch memory allocation fix,
Bruno Haible <=