summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ldap/servers/plugins/syntaxes/string.c74
-rw-r--r--ldap/servers/slapd/regex.c92
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 ) );
+}