Use a single malloc'd block for all the temporary IDL storage in the

filter processing, to avoid runtime stack blowout. Also removes the
need for gigantic thread stacks.
This commit is contained in:
Howard Chu 2002-03-18 11:40:58 +00:00
parent bad62d2167
commit cc21d814b3
3 changed files with 34 additions and 26 deletions

View file

@ -39,14 +39,16 @@ static int list_candidates(
Filter *flist,
int ftype,
ID *ids,
ID *tmp );
ID *tmp,
ID *stack );
int
bdb_filter_candidates(
Backend *be,
Filter *f,
ID *ids,
ID *tmp )
ID *tmp,
ID *stack )
{
int rc = -1;
#ifdef NEW_LOGGING
@ -146,7 +148,7 @@ bdb_filter_candidates(
Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
#endif
rc = list_candidates( be,
f->f_and, LDAP_FILTER_AND, ids, tmp );
f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
break;
case LDAP_FILTER_OR:
@ -156,7 +158,7 @@ bdb_filter_candidates(
Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
#endif
rc = list_candidates( be,
f->f_or, LDAP_FILTER_OR, ids, tmp );
f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
break;
default:
@ -187,20 +189,13 @@ list_candidates(
Filter *flist,
int ftype,
ID *ids,
ID *tmp )
ID *tmp,
ID *save )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
int rc = 0;
Filter *f;
/* Systems that can't increase thread stack size will die with these
* structures allocated on the stack. */
#if !defined(LDAP_PVT_THREAD_STACK_SIZE) || (LDAP_PVT_THREAD_STACK_SIZE == 0)
ID *save = ch_malloc(BDB_IDL_UM_SIZEOF);
#else
ID save[BDB_IDL_UM_SIZE];
#endif
#ifdef NEW_LOGGING
LDAP_LOG (( "filterindex", LDAP_LEVEL_ARGS, "=> bdb_list_candidates: 0x%x\n", ftype));
#else
@ -215,7 +210,8 @@ list_candidates(
}
for ( f = flist; f != NULL; f = f->f_next ) {
rc = bdb_filter_candidates( be, f, save, tmp );
rc = bdb_filter_candidates( be, f, save, tmp,
save+BDB_IDL_UM_SIZE );
if ( rc != 0 ) {
if ( ftype == LDAP_FILTER_AND ) {
@ -235,10 +231,6 @@ list_candidates(
}
}
#if !defined(LDAP_PVT_THREAD_STACK_SIZE) || (LDAP_PVT_THREAD_STACK_SIZE == 0)
free(save);
#endif
if( rc ) {
#ifdef NEW_LOGGING
LDAP_LOG (( "filterindex", LDAP_LEVEL_RESULTS, "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n", (long) ids[0], (long) BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ) ));

View file

@ -120,7 +120,8 @@ int bdb_filter_candidates(
Backend *be,
Filter *f,
ID *ids,
ID *tmp );
ID *tmp,
ID *stack );
/*
* group.c

View file

@ -541,14 +541,19 @@ static int base_candidate(
}
/* Is "objectClass=xx" mentioned anywhere in this filter? Presence
* doesn't count, we're looking for explicit values.
* doesn't count, we're looking for explicit values. Also count depth
* of filter tree while we're at it.
*/
static int oc_filter(
Filter *f
Filter *f,
int cur,
int *max
)
{
int rc = 0;
if( cur > *max ) *max = cur;
switch(f->f_choice) {
case LDAP_FILTER_EQUALITY:
case LDAP_FILTER_APPROX:
@ -563,8 +568,9 @@ static int oc_filter(
case LDAP_FILTER_AND:
case LDAP_FILTER_OR:
cur++;
for (f=f->f_and; f; f=f->f_next)
if ((rc = oc_filter(f)))
if ((rc = oc_filter(f, cur, max)))
break;
break;
default:
@ -582,9 +588,9 @@ static int search_candidates(
int deref,
ID *ids )
{
int rc;
int rc, depth = 1;
Filter f, scopef, rf, xf;
ID tmp[BDB_IDL_UM_SIZE];
ID *stack;
AttributeAssertion aa_ref;
#ifdef BDB_SUBENTRIES
Filter sf;
@ -618,7 +624,7 @@ static int search_candidates(
/* If the user's filter doesn't mention objectClass, or if
* it just uses objectClass=*, these clauses are redundant.
*/
if (oc_filter(filter) && !get_subentries_visibility(op) ) {
if (oc_filter(filter, 1, &depth) && !get_subentries_visibility(op) ) {
if( !get_manageDSAit(op) ) { /* match referrals */
struct berval bv_ref = { sizeof("REFERRAL")-1, "REFERRAL" };
rf.f_choice = LDAP_FILTER_EQUALITY;
@ -640,6 +646,8 @@ static int search_candidates(
xf.f_or = &af;
}
#endif
/* We added one of these clauses, filter depth increased */
if( xf.f_or != filter ) depth++;
}
f.f_next = NULL;
@ -650,6 +658,8 @@ static int search_candidates(
: SLAPD_FILTER_DN_ONE;
scopef.f_dn = &e->e_nname;
scopef.f_next = xf.f_or == filter ? filter : &xf ;
/* Filter depth increased again, adding scope clause */
depth++;
#ifdef BDB_SUBENTRIES
if( get_subentries_visibility( op ) ) {
@ -663,7 +673,12 @@ static int search_candidates(
}
#endif
rc = bdb_filter_candidates( be, &f, ids, tmp );
/* Allocate IDL stack, plus 1 more for former tmp */
stack = malloc( (depth + 1) * BDB_IDL_UM_SIZE * sizeof( ID ) );
rc = bdb_filter_candidates( be, &f, ids, stack, stack+BDB_IDL_UM_SIZE );
free( stack );
if( rc ) {
#ifdef NEW_LOGGING