diff options
-rw-r--r-- | ldap/servers/plugins/syntaxes/string.c | 74 | ||||
-rw-r--r-- | ldap/servers/slapd/regex.c | 92 |
2 files changed, 106 insertions, 60 deletions
diff --git a/ldap/servers/plugins/syntaxes/string.c b/ldap/servers/plugins/syntaxes/string.c index 945b69bf..c0701978 100644 --- a/ldap/servers/plugins/syntaxes/string.c +++ b/ldap/servers/plugins/syntaxes/string.c @@ -189,8 +189,8 @@ int string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, Slapi_Value **bvals, int syntax ) { - int i, j, rc; - char *p, *end, *realval, *tmpbuf; + int i, j, rc, size=0; + char *p, *end, *realval, *tmpbuf, *bigpat = NULL; size_t tmpbufsize; char pat[BUFSIZ]; char buf[BUFSIZ]; @@ -198,7 +198,6 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, LDAPDebug( LDAP_DEBUG_FILTER, "=> string_filter_sub\n", 0, 0, 0 ); - /* * construct a regular expression corresponding to the * filter and let regex do the work for each value @@ -207,16 +206,33 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, pat[0] = '\0'; p = pat; end = pat + sizeof(pat) - 2; /* leave room for null */ + if ( initial != NULL ) { - value_normalize( initial, syntax, 1 /* trim leading blanks */ ); - strcpy( p, "^" ); - p = strchr( p, '\0' ); - /* 2 * in case every char is special */ - if ( p + 2 * strlen( initial ) > end ) { - LDAPDebug( LDAP_DEBUG_ANY, "not enough pattern space\n", - 0, 0, 0 ); - return( -1 ); + size = strlen( initial ) + 1; /* add 1 for "^" */ + } + + if ( any != NULL ) { + i = 0; + while ( any[i] ) { + size += strlen(any[i++]) + 2; /* add 2 for ".*" */ } + } + + if ( final != NULL ) { + size += strlen( final ) + 3; /* add 3 for ".*" and "$" */ + } + + size *= 2; /* doubled in case all filter chars need escaping */ + size++; /* add 1 for null */ + + if ( p + size > end ) { + bigpat = slapi_ch_malloc( size ); + p = bigpat; + } + + if ( initial != NULL ) { + value_normalize( initial, syntax, 1 /* trim leading blanks */ ); + *p++ = '^'; filter_strcpy_special( p, initial ); p = strchr( p, '\0' ); } @@ -224,13 +240,8 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, for ( i = 0; any[i] != NULL; i++ ) { value_normalize( any[i], syntax, 0 /* DO NOT trim leading blanks */ ); /* ".*" + value */ - if ( p + 2 * strlen( any[i] ) + 2 > end ) { - LDAPDebug( LDAP_DEBUG_ANY, - "not enough pattern space\n", 0, 0, 0 ); - return( -1 ); - } - strcpy( p, ".*" ); - p = strchr( p, '\0' ); + *p++ = '.'; + *p++ = '*'; filter_strcpy_special( p, any[i] ); p = strchr( p, '\0' ); } @@ -238,28 +249,26 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, if ( final != NULL ) { value_normalize( final, syntax, 0 /* DO NOT trim leading blanks */ ); /* ".*" + value */ - if ( p + 2 * strlen( final ) + 2 > end ) { - LDAPDebug( LDAP_DEBUG_ANY, "not enough pattern space\n", - 0, 0, 0 ); - return( -1 ); - } - strcpy( p, ".*" ); - p = strchr( p, '\0' ); + *p++ = '.'; + *p++ = '*'; filter_strcpy_special( p, final ); - p = strchr( p, '\0' ); - strcpy( p, "$" ); + strcat( p, "$" ); } /* compile the regex */ + p = (bigpat) ? bigpat : pat; slapd_re_lock(); - if ( (p = slapd_re_comp( pat )) != 0 ) { + if ( (tmpbuf = slapd_re_comp( p )) != 0 ) { LDAPDebug( LDAP_DEBUG_ANY, "re_comp (%s) failed (%s)\n", pat, p, 0 ); slapd_re_unlock(); - return( -1 ); + if( bigpat != NULL ) { + slapi_ch_free((void**)&bigpat ); + } + return( LDAP_OPERATIONS_ERROR ); } else { - LDAPDebug( LDAP_DEBUG_TRACE, "re_comp (%s)\n", - escape_string( pat, ebuf ), 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "re_comp (%s)\n", + escape_string( p, ebuf ), 0, 0 ); } /* @@ -300,6 +309,9 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, if ( tmpbuf != NULL ) { slapi_ch_free((void**)&tmpbuf ); } + if( bigpat != NULL ) { + slapi_ch_free((void**)&bigpat ); + } LDAPDebug( LDAP_DEBUG_FILTER, "<= string_filter_sub %d\n", rc, 0, 0 ); diff --git a/ldap/servers/slapd/regex.c b/ldap/servers/slapd/regex.c index 6f423525..9fe06a76 100644 --- a/ldap/servers/slapd/regex.c +++ b/ldap/servers/slapd/regex.c @@ -43,31 +43,6 @@ #include "slap.h" /* must come before regex.h */ #include "portable.h" -static PRLock *regex_mutex = NULL; - -int -slapd_re_init( void ) -{ - if ( NULL == regex_mutex ) { - regex_mutex = PR_NewLock(); - } - return( NULL == regex_mutex ? -1 : 0 ); -} - -void -slapd_re_lock( void ) -{ - PR_ASSERT( NULL != regex_mutex ); - PR_Lock( regex_mutex ); -} - -int -slapd_re_unlock( void ) -{ - PR_ASSERT( NULL != regex_mutex ); - return( PR_Unlock( regex_mutex ) ); -} - #if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || defined( NEED_BSDREGEX ) #include "regex.h" @@ -91,6 +66,13 @@ slapd_re_unlock( void ) * Modification history: * * $Log: regex.c,v $ + * Revision 1.6 2008/04/29 00:38:36 nhosoi + * Resolves: #182621 (#443955) + * Summary: Allow larger regex buffer to enable long substring filters + * Description: Applying the patches provided by ulf.weltman@hp.com. + * regex.c: use dynamically allocated regex buffer, use ptrdiff_t to store the offsets to be restored after the realloc, and use a constant for the value of "how much the NFA buffer can grow in one iteration on the pattern". + * string.c: use dynamically allocated buffer if the prepared buffer is not large enough, used wrong pointer (pat instead of p) in a debug message, and performed an unneeded strcat of ".*" + * * Revision 1.5 2006/11/10 23:45:40 nhosoi * Resolves: #214533 * Summary: configure needs to support --with-fhs (Comment #6) @@ -416,6 +398,12 @@ slapd_re_unlock( void ) * matches: foo-foo fo-fo fob-fob foobar-foobar ... */ +/* This is the maximum the NFA buffer might grow for every op code processed. + The max seems to be the + after a character class, like "[a-z]+". It + needs 1 byte for the CCL code, 16 for the CCL bit map, and 2 for END codes + and 1 for a CLO code. */ +#define MAXOPSPACE 20 + #define MAXNFA 1024 #define MAXTAG 10 @@ -454,11 +442,12 @@ typedef unsigned char UCHAR; */ static int tagstk[MAXTAG]; /* subpat tag stack..*/ -static UCHAR nfa[MAXNFA]; /* automaton.. */ -static int sta = NOP; /* status of lastpat */ +static UCHAR *nfa = NULL; /* automaton.. */ +static int nfasize = MAXNFA; /* tracks size of nfa buffer */ +static int sta = NOP; /* status of lastpat */ -static UCHAR bittab[BITBLK]; /* bit table for CCL */ - /* pre-set bits... */ +static UCHAR bittab[BITBLK]; /* bit table for CCL */ + /* pre-set bits... */ static UCHAR bitarr[] = {1,2,4,8,16,32,64,128}; #ifdef DEBUG @@ -498,6 +487,21 @@ slapd_re_comp( char *pat ) sta = NOP; for (p = (UCHAR*)pat; *p; p++) { + /* Check if we are approaching end of nfa buffer. MAXOPSPACE is + the max we might add to the nfa per loop. */ + if (mp - (UCHAR*)nfa + MAXOPSPACE >= nfasize) { + /* Save offsets */ + ptrdiff_t mppos = mp - nfa; + ptrdiff_t sppos = sp - nfa; + + /* Double the nfa buffer size */ + nfasize *= 2; + nfa = (UCHAR*)slapi_ch_realloc((char*)nfa, nfasize); + + /* Restore pointers into realloced space */ + mp = nfa + mppos; + sp = nfa + sppos; + } lp = mp; switch(*p) { @@ -1099,3 +1103,33 @@ nfadump( UCHAR *ap) } #endif #endif /* MACOS or DOS or NEED_BSDREGEX */ + +static PRLock *regex_mutex = NULL; + +int +slapd_re_init( void ) +{ + if ( NULL == regex_mutex ) { + regex_mutex = PR_NewLock(); + } + + if ( NULL == nfa ) { + nfa = (UCHAR*)slapi_ch_malloc( MAXNFA ); + } + + return( NULL == regex_mutex ? -1 : 0 ); +} + +void +slapd_re_lock( void ) +{ + PR_ASSERT( NULL != regex_mutex ); + PR_Lock( regex_mutex ); +} + +int +slapd_re_unlock( void ) +{ + PR_ASSERT( NULL != regex_mutex ); + return( PR_Unlock( regex_mutex ) ); +} |