[Copying some discussion from IRC, and adding some more] I'm a bit nervous about doing more than minimal fixes to this until we do something major, because it's so broken. Fix one bit and maybe something will pop up another place - i.e. a regression. Also following existing practice can mean fix one bug into a different bug, which Ando recently did for ITS#6423. (dynlist resets MUSTRELEASE but doesn't obey it, rwm works around a similar bug in rwm or dynlist.) Though he got other fixes right. Anyway: To repeat, the main problems with the current code: * Code does not always clean up properly, leaving e.g. flags behind. * Code which does clean up sometimes does it halfway, e.g. it resets MUSTBEFREED/MUSTRELEASE but not MODIFIABLE. So, no wonder there are unwanted MODIFIABLE flags hanging about (ITS#6423). Or it dup()s an entry but does not release the old one. * op_*() generally expects SlapReply to be preinitialized. That worked before overlays, but now modules (backends, overlays) inherit values that the previous module did not clean up during an operation. Howard suggested that we should restore that - code which puts something into a SlapReply should ensure it's taken out again. I've started on that in the enclosed patch, but on second thought I think that's not the right fix because it's the most fragile solution: Practically every module which depends on it can break if some other module gets it wrong. OTOH, modules can't just reset SlapReply since some of it is input values to op_*(): - Controls can be set in backend_check_restrictions() before the call to op_*(). - dynlist.c sets r.sr_attr_flags before calling o.o_bd->be_search(), I haven't looked at what effect that has. I'm thinking modules should instead initialize SlapReply.sr_u and maybe some sr_flags themselves instead of depending on preinit, but I don't know when I'll get back to doing something about that. Xmas coming... So anyway, here is a quick patch which actually tries to be rather conservative, sans a bunch of RS_ASSERT() lines which can be safely deleted in real code. It only addresses sr_entry and sporadically attrs, not sr_refs/ctrls. It passes make test for me. Please review. Where updates to flags are broken and needs fixing, I change to use the new function rs_ensure_entry_modifiable() etc, but I leave correct updates alone - as well as some updates where I don't know which overlay should be passed to these function. Description of changes: All over the place: Clear MUSTBEFREED/MUSTRELEASE by clearing all of REP_ENTRY_MASK, not just the particular flag. Reset attrs, entry, flags a number of places. (Not very consistently, sorry.) Lots of RS_ASSERT()s for debugging. Only defined when LDAP_DEVEL. proto-slap.h, result.c: Move RS_ASSERT(), add rs_flush_entry(). result.c: MODIFIABLE is independent of MUSTBEFREED - the modifiable entry can e.g. be on the stack. result.c, extended.c: When changing sr->sr_type to extended/sasl, flush sr_un (usually the entry) first, since another member of the union will be used. For this reason, updates to sr_type are "suspicious" code to be avoided, so some code elsewhere is changed to initialize it to REP_RESULT rather than setting it to that after initialization. bconfig.c, servers/slapd/syncrepl.c: Avoid reusing SlapReply a number of places where that's easy. slap.h: Cast the REP_... flags to slap_mask_t, so ~REP_... will work right. back-bdb/search.c: Delay setting rs->sr_entry until we know it'll be used. (IIRC made a difference around a paged results response.) back-shell/result.c, back-sock/result.c: Set MUSTBEFREED before sending, obey it afterwards. overlays/constraint.c, overlays/pcache.c: Drop nulling of fields that were just nulled by initialization. overlays/dynlist.c: When "stealing" an entry from SlapReply, grab and reset the flags that go with it, so it can be properly freed/released. Restore the flags and entry later, then obey the flags (release/free). Do this unconditionally, it happens only once per SlapReply anyway. overlays/pcache.c: Obey and reset entry flags properly. Remove unused SlapReply parameters to some functions - did this for readibility while trying to figure out what was going on. overlays/sssvlv.c: Since setting MUSTRELEASE before sending, obey it afterwards. overlays/translucent.c: Reset flags properly too when releasing/freeing entry. Streamline translucent_search() loop to clarify ownership of entry. overlays/rwm.c, servers/slapd/slapi/slapi_pblock.c: Obey flags properly. Index: servers/slapd/proto-slap.h =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/proto-slap.h,v retrieving revision 1.796 diff -u -2 -r1.796 proto-slap.h --- servers/slapd/proto-slap.h 9 Dec 2009 23:07:35 -0000 1.796 +++ servers/slapd/proto-slap.h 15 Dec 2009 16:40:53 -0000 @@ -1515,4 +1515,12 @@ * result.c */ +#ifdef RS_ASSERT +#elif defined LDAP_DEVEL +#define RS_ASSERT assert +#else +#define RS_ASSERT(cond) ((void) 0) +#endif +LDAP_SLAPD_F (void) rs_flush_entry LDAP_P(( Operation *op, + SlapReply *rs, slap_overinst *on )); LDAP_SLAPD_F (void) rs_replace_entry LDAP_P(( Operation *op, SlapReply *rs, slap_overinst *on, Entry *e )); Index: servers/slapd/result.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/result.c,v retrieving revision 1.338 diff -u -2 -r1.338 result.c --- servers/slapd/result.c 9 Dec 2009 23:07:34 -0000 1.338 +++ servers/slapd/result.c 15 Dec 2009 16:40:53 -0000 @@ -140,7 +140,11 @@ #endif -/* Set rs->sr_entry after obyeing and clearing sr_flags & REP_ENTRY_MASK. */ +/* + * Obey and clear rs->sr_flags & REP_ENTRY_MASK. + * Clear sr_entry if freed. TODO: Should be safe to always clear sr_entry. + * Code expecting sr_entry != NULL after flush is fragile at best. + */ void -rs_replace_entry( Operation *op, SlapReply *rs, slap_overinst *on, Entry *e ) +rs_flush_entry( Operation *op, SlapReply *rs, slap_overinst *on ) { slap_mask_t e_flags = rs->sr_flags & REP_ENTRY_MUSTFLUSH; @@ -148,4 +152,5 @@ if ( e_flags && rs->sr_entry != NULL ) { RS_ASSERT( e_flags != REP_ENTRY_MUSTFLUSH ); + RS_ASSERT( (rs->sr_flags | REP_ENTRY_MUSTBEFREED) != REP_ENTRY_MASK ); if ( !(e_flags & REP_ENTRY_MUSTRELEASE) ) { entry_free( rs->sr_entry ); @@ -155,6 +160,16 @@ be_entry_release_rw( op, rs->sr_entry, 0 ); } + rs->sr_entry = NULL; } + else RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) || rs->sr_entry ); + rs->sr_flags &= ~REP_ENTRY_MASK; +} + +/* Set rs->sr_entry after obeying and clearing sr_flags & REP_ENTRY_MASK. */ +void +rs_replace_entry( Operation *op, SlapReply *rs, slap_overinst *on, Entry *e ) +{ + rs_flush_entry( op, rs, on ); rs->sr_entry = e; } @@ -169,5 +184,5 @@ { if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) { - RS_ASSERT((rs->sr_flags & REP_ENTRY_MUSTFLUSH)==REP_ENTRY_MUSTBEFREED); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTRELEASE) ); return 0; } @@ -543,4 +558,5 @@ ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE )) { + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); if ( rs->sr_rspoid != NULL ) { rc = ber_printf( ber, "ts", @@ -660,4 +676,5 @@ assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_type = REP_EXTENDED; rs->sr_rspdata = NULL; @@ -693,4 +710,5 @@ BerVarray oref = rs->sr_ref; + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_type = REP_RESULT; @@ -770,4 +788,5 @@ send_ldap_sasl( Operation *op, SlapReply *rs ) { + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_type = REP_SASL; Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n", @@ -789,4 +808,5 @@ slap_send_ldap_extended( Operation *op, SlapReply *rs ) { + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_type = REP_EXTENDED; @@ -811,4 +831,5 @@ slap_send_ldap_intermediate( Operation *op, SlapReply *rs ) { + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_type = REP_INTERMEDIATE; Debug( LDAP_DEBUG_TRACE, @@ -1297,5 +1318,5 @@ if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { be_entry_release_rw( op, rs->sr_entry, 0 ); - rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; } @@ -1336,4 +1357,5 @@ } + /* FIXME: Can break if rs now contains an extended response */ if ( rs->sr_operational_attrs ) { attrs_free( rs->sr_operational_attrs ); @@ -1343,8 +1365,11 @@ /* FIXME: I think rs->sr_type should be explicitly set to - * REP_SEARCH here. That's what it was when we entered this + * REP_SEARCH here. That's how we set it on entering this * function. send_ldap_error may have changed it, but we * should set it back so that the cleanup functions know * what they're doing. + * + * Except we may have to clear out rs->sr_un.sru_search first, + * if it can contain data from sr_un.sru_extended. */ if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH @@ -1353,6 +1378,6 @@ { entry_free( rs->sr_entry ); + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; - rs->sr_flags &= ~REP_ENTRY_MUSTBEFREED; } @@ -1468,5 +1493,5 @@ assert( rs->sr_entry != NULL ); be_entry_release_rw( op, rs->sr_entry, 0 ); - rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; } @@ -1619,4 +1644,5 @@ op->o_log_prefix, oid->bv_val, e->e_dn ); + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); rs->sr_entry = e; rs->sr_attrs = ( oid == &slap_pre_read_bv ) ? @@ -1638,4 +1664,8 @@ rc = slap_send_search_entry( &myop, rs ); + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); + rs->sr_flags &= ~REP_ENTRY_MASK; + rs->sr_entry = NULL; + rs->sr_attrs = NULL; if( rc ) return rc; Index: servers/slapd/bconfig.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/bconfig.c,v retrieving revision 1.408 diff -u -2 -r1.408 bconfig.c --- servers/slapd/bconfig.c 11 Dec 2009 17:09:47 -0000 1.408 +++ servers/slapd/bconfig.c 15 Dec 2009 16:40:53 -0000 @@ -3877,5 +3877,4 @@ OperationBuffer opbuf; Operation *op; - SlapReply rs = {REP_RESULT}; Filter filter = { LDAP_FILTER_PRESENT }; struct berval filterstr = BER_BVC("(objectclass=*)"); @@ -3971,5 +3970,9 @@ slap_DN_strict = 0; - rc = op->o_bd->be_search( op, &rs ); + { + SlapReply rs = { REP_RESULT }; + rc = op->o_bd->be_search( op, &rs ); + RS_ASSERT( !(rs.sr_flags & REP_ENTRY_MUSTFLUSH) ); + } /* Restore normal DN validation */ @@ -3978,8 +3981,10 @@ op->o_tag = LDAP_REQ_ADD; if ( rc == LDAP_SUCCESS && sc.frontend ) { + SlapReply rs = { REP_RESULT }; op->ora_e = sc.frontend; rc = op->o_bd->be_add( op, &rs ); } if ( rc == LDAP_SUCCESS && sc.config ) { + SlapReply rs = { REP_RESULT }; op->ora_e = sc.config; rc = op->o_bd->be_add( op, &rs ); @@ -4137,4 +4142,7 @@ rs->sr_flags = 0; rc = send_search_entry( op, rs ); + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); + rs->sr_entry = NULL; + rs->sr_flags = 0; if ( rc != LDAP_SUCCESS ) { return rc; Index: servers/slapd/extended.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/extended.c,v retrieving revision 1.99 diff -u -2 -r1.99 extended.c --- servers/slapd/extended.c 21 Jan 2009 23:40:26 -0000 1.99 +++ servers/slapd/extended.c 15 Dec 2009 16:40:53 -0000 @@ -248,8 +248,10 @@ if ( rs->sr_rspoid != NULL ) { free( (char *)rs->sr_rspoid ); + rs->sr_rspoid = NULL; } if ( rs->sr_rspdata != NULL ) { ber_bvfree( rs->sr_rspdata ); + rs->sr_rspdata = NULL; } } /* end of OpenLDAP extended operation */ Index: servers/slapd/saslauthz.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/saslauthz.c,v retrieving revision 1.179 diff -u -2 -r1.179 saslauthz.c --- servers/slapd/saslauthz.c 21 Jan 2009 23:40:27 -0000 1.179 +++ servers/slapd/saslauthz.c 15 Dec 2009 16:40:53 -0000 @@ -1834,4 +1834,5 @@ op.o_bd->be_search( &op, &rs ); + RS_ASSERT( !(rs.sr_flags & REP_ENTRY_MUSTFLUSH) ); if (sm.match) { @@ -2004,4 +2005,5 @@ op.o_bd->be_search( &op, &rs ); + RS_ASSERT( !(rs.sr_flags & REP_ENTRY_MUSTFLUSH) ); FINISHED: Index: servers/slapd/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/search.c,v retrieving revision 1.192 diff -u -2 -r1.192 search.c --- servers/slapd/search.c 11 Nov 2009 00:42:00 -0000 1.192 +++ servers/slapd/search.c 15 Dec 2009 16:40:53 -0000 @@ -216,4 +216,5 @@ op->o_bd = frontendDB; rs->sr_err = frontendDB->be_search( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); return_results:; @@ -290,4 +291,6 @@ rs->sr_flags = 0; send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; rs->sr_operational_attrs = NULL; Index: servers/slapd/slap.h =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/slap.h,v retrieving revision 1.887 diff -u -2 -r1.887 slap.h --- servers/slapd/slap.h 10 Dec 2009 18:54:57 -0000 1.887 +++ servers/slapd/slap.h 15 Dec 2009 16:40:54 -0000 @@ -2094,21 +2094,21 @@ } sr_un; slap_mask_t sr_flags; -#define REP_ENTRY_MODIFIABLE 0x0001U -#define REP_ENTRY_MUSTBEFREED 0x0002U -#define REP_ENTRY_MUSTRELEASE 0x0004U -#define REP_ENTRY_MASK (REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED|REP_ENTRY_MUSTRELEASE) +#define REP_ENTRY_MODIFIABLE ((slap_mask_t) 0x0001U) +#define REP_ENTRY_MUSTBEFREED ((slap_mask_t) 0x0002U) +#define REP_ENTRY_MUSTRELEASE ((slap_mask_t) 0x0004U) +#define REP_ENTRY_MASK (REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTFLUSH) #define REP_ENTRY_MUSTFLUSH (REP_ENTRY_MUSTBEFREED|REP_ENTRY_MUSTRELEASE) -#define REP_MATCHED_MUSTBEFREED 0x0010U +#define REP_MATCHED_MUSTBEFREED ((slap_mask_t) 0x0010U) #define REP_MATCHED_MASK (REP_MATCHED_MUSTBEFREED) -#define REP_REF_MUSTBEFREED 0x0020U +#define REP_REF_MUSTBEFREED ((slap_mask_t) 0x0020U) #define REP_REF_MASK (REP_REF_MUSTBEFREED) -#define REP_CTRLS_MUSTBEFREED 0x0040U +#define REP_CTRLS_MUSTBEFREED ((slap_mask_t) 0x0040U) #define REP_CTRLS_MASK (REP_CTRLS_MUSTBEFREED) -#define REP_NO_ENTRYDN 0x1000U -#define REP_NO_SUBSCHEMA 0x2000U +#define REP_NO_ENTRYDN ((slap_mask_t) 0x1000U) +#define REP_NO_SUBSCHEMA ((slap_mask_t) 0x2000U) #define REP_NO_OPERATIONALS (REP_NO_ENTRYDN|REP_NO_SUBSCHEMA) }; Index: servers/slapd/syncrepl.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/syncrepl.c,v retrieving revision 1.500 diff -u -2 -r1.500 syncrepl.c --- servers/slapd/syncrepl.c 8 Dec 2009 23:04:58 -0000 1.500 +++ servers/slapd/syncrepl.c 15 Dec 2009 16:40:54 -0000 @@ -480,4 +480,5 @@ ldap_pvt_thread_mutex_lock( &si->si_cookieState->cs_mutex ); i = backend_operational( op, &rs ); + RS_ASSERT( !(rs.sr_flags & REP_ENTRY_MUSTFLUSH) ); if ( i == LDAP_SUCCESS && a.a_nvals ) { int num = a.a_numvals; @@ -2352,4 +2353,5 @@ rc = be->be_search( &op2, &rs2 ); + RS_ASSERT( !(rs2.sr_flags & REP_ENTRY_MUSTFLUSH) ); if ( rc ) goto done; @@ -2679,5 +2681,4 @@ Backend* be = op->o_bd; slap_callback cb = { NULL }; - SlapReply rs_search = {REP_RESULT}; SlapReply rs_delete = {REP_RESULT}; SlapReply rs_modify = {REP_RESULT}; @@ -2720,8 +2721,11 @@ for (i=0; uuids[i].bv_val; i++) { + SlapReply rs_search = {REP_RESULT}; + op->ors_slimit = 1; uf.f_av_value = uuids[i]; filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); rc = be->be_search( op, &rs_search ); + RS_ASSERT( !(rs_search.sr_flags & REP_ENTRY_MUSTFLUSH) ); op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } @@ -2773,6 +2777,9 @@ op->o_nocaching = 1; - - rc = be->be_search( op, &rs_search ); + { + SlapReply rs_search = {REP_RESULT}; + rc = be->be_search( op, &rs_search ); + RS_ASSERT( !(rs_search.sr_flags & REP_ENTRY_MUSTFLUSH) ); + } if ( SLAP_MULTIMASTER( op->o_bd )) { op->ors_filter = of; Index: servers/slapd/back-bdb/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-bdb/search.c,v retrieving revision 1.277 diff -u -2 -r1.277 search.c --- servers/slapd/back-bdb/search.c 19 Aug 2009 11:02:54 -0000 1.277 +++ servers/slapd/back-bdb/search.c 15 Dec 2009 16:40:54 -0000 @@ -337,4 +337,5 @@ Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_search) "\n", 0, 0, 0); + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); attrs = op->oq_search.rs_attrs; @@ -749,6 +750,4 @@ } - rs->sr_entry = e; - if ( is_entry_subentry( e ) ) { if( op->oq_search.rs_scope != LDAP_SCOPE_BASE ) { @@ -882,4 +881,6 @@ blis.bli_flag = BLI_DONTFREE; + RS_ASSERT( e != NULL ); + rs->sr_entry = e; rs->sr_flags = REP_ENTRY_MUSTRELEASE; @@ -898,4 +899,5 @@ } } + rs->sr_flags = 0; rs->sr_entry = NULL; e = NULL; @@ -913,5 +915,5 @@ /* if it matches the filter and scope, send it */ - rs->sr_err = test_filter( op, rs->sr_entry, op->oq_search.rs_filter ); + rs->sr_err = test_filter( op, e, op->oq_search.rs_filter ); if ( rs->sr_err == LDAP_COMPARE_TRUE ) { @@ -925,4 +927,5 @@ e = NULL; send_paged_response( op, rs, &lastid, tentries ); + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); goto done; } @@ -930,4 +933,5 @@ } + RS_ASSERT(e != NULL); if (e) { struct bdb_op_info bois; @@ -954,10 +958,13 @@ /* safe default */ + RS_ASSERT( e != NULL ); rs->sr_attrs = op->oq_search.rs_attrs; rs->sr_operational_attrs = NULL; rs->sr_ctrls = NULL; + rs->sr_entry = e; rs->sr_flags = REP_ENTRY_MUSTRELEASE; rs->sr_err = LDAP_SUCCESS; rs->sr_err = send_search_entry( op, rs ); + rs->sr_attrs = NULL; /* send_search_entry will usually free it. @@ -977,4 +984,5 @@ } } + rs->sr_flags = 0; rs->sr_entry = NULL; e = NULL; @@ -1015,4 +1023,5 @@ e = NULL; rs->sr_entry = NULL; + rs->sr_flags &= ~REP_ENTRY_MASK; } } @@ -1324,3 +1333,2 @@ (void) ber_free_buf( ber ); } - Index: servers/slapd/back-dnssrv/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-dnssrv/search.c,v retrieving revision 1.49 diff -u -2 -r1.49 search.c --- servers/slapd/back-dnssrv/search.c 21 Jan 2009 23:40:32 -0000 1.49 +++ servers/slapd/back-dnssrv/search.c 15 Dec 2009 16:40:54 -0000 @@ -218,4 +218,6 @@ rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); + rs->sr_flags = 0; rs->sr_entry = NULL; rs->sr_attrs = NULL; Index: servers/slapd/back-ldap/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-ldap/search.c,v retrieving revision 1.261 diff -u -2 -r1.261 search.c --- servers/slapd/back-ldap/search.c 7 Oct 2009 20:46:35 -0000 1.261 +++ servers/slapd/back-ldap/search.c 15 Dec 2009 16:40:54 -0000 @@ -174,4 +174,6 @@ const char *save_matched = rs->sr_matched; + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); + if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; @@ -344,4 +346,6 @@ rs->sr_ctrls = NULL; } + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; if ( !BER_BVISNULL( &ent.e_name ) ) { @@ -402,4 +406,5 @@ /* ignore return value by now */ + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_entry = NULL; ( void )send_search_reference( op, rs ); Index: servers/slapd/back-ldif/ldif.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-ldif/ldif.c,v retrieving revision 1.106 diff -u -2 -r1.106 ldif.c --- servers/slapd/back-ldif/ldif.c 3 Dec 2009 22:20:39 -0000 1.106 +++ servers/slapd/back-ldif/ldif.c 15 Dec 2009 16:40:54 -0000 @@ -648,5 +648,8 @@ rs->sr_ref = referral_rewrite( refs, &e->e_name, NULL, scope ); rs->sr_entry = e; + RS_ASSERT( !(rs->sr_flags & (REP_ENTRY_MASK|REP_REF_MASK)) ); rc = send_search_reference( op, rs ); + RS_ASSERT( !(rs->sr_flags & (REP_ENTRY_MASK|REP_REF_MASK)) ); + rs->sr_flags &= ~(REP_ENTRY_MASK | REP_REF_MASK); ber_bvarray_free( rs->sr_ref ); ber_bvarray_free( refs ); @@ -656,9 +659,17 @@ else if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_entry = e; rs->sr_attrs = op->ors_attrs; + /* Could set REP_ENTRY_MUSTBEFREED too for efficiency, + * but refraining lets us test unFREEable MODIFIABLE + * entries. Like entries built on the stack. + */ rs->sr_flags = REP_ENTRY_MODIFIABLE; rc = send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); + rs->sr_flags = 0; rs->sr_entry = NULL; + rs->sr_attrs = NULL; } } @@ -1226,4 +1237,5 @@ struct ldif_info *li = (struct ldif_info *) op->o_bd->be_private; + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); ldap_pvt_thread_rdwr_rlock(&li->li_rdwr); rs->sr_err = search_tree( op, rs ); Index: servers/slapd/back-meta/conn.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-meta/conn.c,v retrieving revision 1.135 diff -u -2 -r1.135 conn.c --- servers/slapd/back-meta/conn.c 23 Aug 2009 22:41:13 -0000 1.135 +++ servers/slapd/back-meta/conn.c 15 Dec 2009 16:40:54 -0000 @@ -865,5 +865,5 @@ } else if ( candidate == META_TARGET_MULTIPLE ) { Operation op2 = *op; - SlapReply rs2 = { 0 }; + SlapReply rs2 = { REP_RESULT }; slap_callback cb2 = { 0 }; int rc; @@ -890,4 +890,5 @@ rc = op->o_bd->be_search( &op2, &rs2 ); + RS_ASSERT( !(rs2.sr_flags & REP_ENTRY_MUSTFLUSH) ); switch ( rs2.sr_err ) { Index: servers/slapd/back-meta/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-meta/search.c,v retrieving revision 1.225 diff -u -2 -r1.225 search.c --- servers/slapd/back-meta/search.c 13 Aug 2009 17:30:37 -0000 1.225 +++ servers/slapd/back-meta/search.c 15 Dec 2009 16:40:54 -0000 @@ -675,4 +675,5 @@ SlapReply *candidates = NULL; + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); /* * controls are set in ldap_back_dobind() @@ -2206,4 +2207,5 @@ done:; + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; rs->sr_attrs = NULL; Index: servers/slapd/back-monitor/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-monitor/search.c,v retrieving revision 1.45 diff -u -2 -r1.45 search.c --- servers/slapd/back-monitor/search.c 21 Jan 2009 23:40:35 -0000 1.45 +++ servers/slapd/back-monitor/search.c 15 Dec 2009 16:40:54 -0000 @@ -114,4 +114,6 @@ rs->sr_flags = 0; rc = send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; } @@ -221,4 +223,6 @@ rs->sr_flags = 0; send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; } @@ -240,4 +244,6 @@ rs->sr_flags = 0; send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; rs->sr_entry = NULL; } Index: servers/slapd/back-passwd/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-passwd/search.c,v retrieving revision 1.82 diff -u -2 -r1.82 search.c --- servers/slapd/back-passwd/search.c 21 Jan 2009 23:40:36 -0000 1.82 +++ servers/slapd/back-passwd/search.c 15 Dec 2009 16:40:54 -0000 @@ -124,4 +124,7 @@ rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); + rs->sr_flags = 0; + rs->sr_attrs = NULL; } @@ -174,4 +177,7 @@ rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); + rs->sr_flags = 0; + rs->sr_entry = NULL; } @@ -239,4 +245,8 @@ rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); + rs->sr_flags = 0; + rs->sr_entry = NULL; + rs->sr_attrs = NULL; } Index: servers/slapd/back-perl/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-perl/search.c,v retrieving revision 1.35 diff -u -2 -r1.35 search.c --- servers/slapd/back-perl/search.c 21 Jan 2009 23:40:36 -0000 1.35 +++ servers/slapd/back-perl/search.c 15 Dec 2009 16:40:54 -0000 @@ -93,6 +93,9 @@ rs->sr_err = LDAP_SUCCESS; rs->sr_err = send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); + rs->sr_flags = 0; + rs->sr_attrs = NULL; + rs->sr_entry = NULL; if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) { - rs->sr_entry = NULL; goto done; } @@ -125,3 +128,2 @@ return 0; } - Index: servers/slapd/back-shell/result.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-shell/result.c,v retrieving revision 1.27 diff -u -2 -r1.27 result.c --- servers/slapd/back-shell/result.c 21 Jan 2009 23:40:37 -0000 1.27 +++ servers/slapd/back-shell/result.c 15 Dec 2009 16:40:54 -0000 @@ -101,7 +101,8 @@ } else { rs->sr_attrs = op->oq_search.rs_attrs; - rs->sr_flags = REP_ENTRY_MODIFIABLE; + rs->sr_flags = REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; send_search_entry( op, rs ); - entry_free( rs->sr_entry ); + rs_replace_entry( op, rs, NULL, NULL ); + rs->sr_attrs = NULL; } Index: servers/slapd/back-sock/result.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-sock/result.c,v retrieving revision 1.5 diff -u -2 -r1.5 result.c --- servers/slapd/back-sock/result.c 21 Jan 2009 23:40:37 -0000 1.5 +++ servers/slapd/back-sock/result.c 15 Dec 2009 16:40:54 -0000 @@ -98,7 +98,8 @@ } else { rs->sr_attrs = op->oq_search.rs_attrs; - rs->sr_flags = REP_ENTRY_MODIFIABLE; + rs->sr_flags = REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; send_search_entry( op, rs ); - entry_free( rs->sr_entry ); + rs_replace_entry( op, rs, NULL, NULL ); + rs->sr_attrs = NULL; } Index: servers/slapd/back-sql/search.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-sql/search.c,v retrieving revision 1.138 diff -u -2 -r1.138 search.c --- servers/slapd/back-sql/search.c 3 Aug 2009 11:08:22 -0000 1.138 +++ servers/slapd/back-sql/search.c 15 Dec 2009 16:40:54 -0000 @@ -2367,4 +2367,6 @@ send_search_reference( op, rs ); + RS_ASSERT( !(rs->sr_flags & (REP_ENTRY_MASK|REP_REF_MASK)) ); + rs->sr_flags &= ~(REP_ENTRY_MASK|REP_REF_MASK); ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; @@ -2460,4 +2462,6 @@ rs->sr_err = send_search_entry( op, rs ); e->e_private = NULL; + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); + rs->sr_flags = 0; rs->sr_entry = NULL; rs->sr_attrs = NULL; Index: servers/slapd/overlays/constraint.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/constraint.c,v retrieving revision 1.25 diff -u -2 -r1.25 constraint.c --- servers/slapd/overlays/constraint.c 19 Oct 2008 19:23:06 -0000 1.25 +++ servers/slapd/overlays/constraint.c 15 Dec 2009 16:40:54 -0000 @@ -567,7 +567,4 @@ found = 0; - nrs.sr_entry = NULL; - nrs.sr_nentries = 0; - cb.sc_next = NULL; cb.sc_response = constraint_uri_cb; @@ -664,5 +661,4 @@ if (!found) return LDAP_CONSTRAINT_VIOLATION; /* constraint violation */ - } Index: servers/slapd/overlays/dynlist.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/dynlist.c,v retrieving revision 1.69 diff -u -2 -r1.69 dynlist.c --- servers/slapd/overlays/dynlist.c 8 Dec 2009 17:47:17 -0000 1.69 +++ servers/slapd/overlays/dynlist.c 15 Dec 2009 16:40:54 -0000 @@ -211,4 +211,5 @@ dynlist_info_t *dlc_dli; Entry *dlc_e; + slap_mask_t dlc_eflags; } dynlist_sc_t; @@ -395,9 +396,5 @@ done:; - if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { - entry_free( rs->sr_entry ); - rs->sr_entry = NULL; - rs->sr_flags ^= REP_ENTRY_MUSTBEFREED; - } + rs_flush_entry( op, rs, (slap_overinst *) op->o_bd->bd_info ); return 0; @@ -455,4 +452,5 @@ return SLAP_CB_CONTINUE; } + RS_ASSERT( o.o_ndn.bv_val == NULL ? op->o_ndn.bv_val == NULL : dn_match( &o.o_ndn, &op->o_ndn )); } @@ -462,12 +460,7 @@ } + rs_ensure_entry_modifiable( op, rs, (slap_overinst *)op->o_bd->bd_info ); e_flags = rs->sr_flags; - if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) { - e = entry_dup( rs->sr_entry ); - e_flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED ); - e_flags &= ~REP_ENTRY_MUSTRELEASE; - } else { - e = rs->sr_entry; - } + e = rs->sr_entry; dlc.dlc_e = e; @@ -664,6 +657,6 @@ } - rs->sr_entry = e; - rs->sr_flags = e_flags; + RS_ASSERT( rs->sr_entry == e ); + RS_ASSERT( rs->sr_flags == e_flags ); return SLAP_CB_CONTINUE; @@ -675,9 +668,9 @@ /* save the entry in the private field of the callback, * so it doesn't get freed (it's temporary!) */ - if ( rs->sr_entry != NULL ) { - dynlist_sc_t *dlc = (dynlist_sc_t *)op->o_callback->sc_private; - dlc->dlc_e = rs->sr_entry; - rs->sr_entry = NULL; - } + dynlist_sc_t *dlc = (dynlist_sc_t *)op->o_callback->sc_private; + dlc->dlc_e = rs->sr_entry; + dlc->dlc_eflags = rs->sr_flags & REP_ENTRY_MASK; + rs->sr_entry = NULL; + rs->sr_flags &= ~REP_ENTRY_MASK; return 0; @@ -835,17 +828,11 @@ } - if ( rc != 0 ) { - goto release; - } + r.sr_entry = dlc.dlc_e; + r.sr_flags = dlc.dlc_eflags; - if ( dlc.dlc_e != NULL ) { - r.sr_entry = dlc.dlc_e; + if ( rc != 0 || r.sr_err != LDAP_SUCCESS || r.sr_entry == NULL ) { + dli = NULL; } - - if ( r.sr_err != LDAP_SUCCESS || r.sr_entry == NULL ) { - /* error? */ - goto release; - } - + else for ( a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc ); a != NULL; @@ -865,9 +852,5 @@ } - if ( r.sr_flags & REP_ENTRY_MUSTBEFREED ) { - entry_free( r.sr_entry ); - r.sr_entry = NULL; - r.sr_flags ^= REP_ENTRY_MUSTBEFREED; - } + rs_flush_entry( &o, &r, on ); } Index: servers/slapd/overlays/pcache.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/pcache.c,v retrieving revision 1.202 diff -u -2 -r1.202 pcache.c --- servers/slapd/overlays/pcache.c 23 Nov 2009 15:04:00 -0000 1.202 +++ servers/slapd/overlays/pcache.c 15 Dec 2009 16:40:54 -0000 @@ -347,5 +347,4 @@ remove_query_data( Operation *op, - SlapReply *rs, struct berval *query_uuid ); @@ -753,9 +752,8 @@ if ( expiry_time <= slap_get_time()) { Operation op2 = *op; - SlapReply rs2 = { 0 }; memset( &op2.oq_search, 0, sizeof( op2.oq_search ) ); - (void)remove_query_data( &op2, &rs2, &uuid ); + (void) remove_query_data( &op2, &uuid ); rc = 0; @@ -1747,5 +1745,4 @@ remove_query_data( Operation *op, - SlapReply *rs, struct berval *query_uuid ) { @@ -1758,6 +1755,4 @@ int deleted = 0; - sreply.sr_entry = NULL; - sreply.sr_nentries = 0; op->ors_filterstr.bv_len = snprintf(filter_str, sizeof(filter_str), "(%s=%s)", ad_queryId->ad_cname.bv_val, query_uuid->bv_val); @@ -1970,5 +1965,4 @@ remove_query_and_data( Operation *op, - SlapReply *rs, cache_manager *cm, struct berval *uuid ) @@ -1983,5 +1977,5 @@ "Removing query UUID %s\n", uuid->bv_val, 0, 0 ); - return_val = remove_query_data( op, rs, uuid ); + return_val = remove_query_data( op, uuid ); Debug( pcache_debug, "QUERY REMOVED, SIZE=%d\n", @@ -2033,9 +2027,5 @@ /* clear entry if required */ - if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { - entry_free( rs->sr_entry ); - rs->sr_entry = NULL; - rs->sr_flags ^= REP_ENTRY_MUSTBEFREED; - } + rs_flush_entry( op, rs, (slap_overinst *) op->o_bd->bd_info ); return rc; @@ -2121,5 +2111,5 @@ struct berval val = vals[ i ]; - remove_query_and_data( op, &rs, cm, &val ); + remove_query_and_data( op, cm, &val ); if ( !BER_BVISNULL( &val ) && val.bv_val != vals[ i ].bv_val ) { @@ -2146,10 +2136,9 @@ { Operation op2 = *op; - SlapReply rs2 = { 0 }; op2.o_bd = &cm->db; /* remove the selected query */ - remove_query_and_data( &op2, &rs2, cm, queryid ); + remove_query_and_data( &op2, cm, queryid ); return LDAP_SUCCESS; @@ -2242,5 +2231,5 @@ struct berval val = vals[ i ]; - remove_query_and_data( op, &rs, cm, &val ); + remove_query_and_data( op, cm, &val ); if ( !BER_BVISNULL( &val ) && val.bv_val != vals[ i ].bv_val ) { @@ -2258,5 +2247,4 @@ cache_entries( Operation *op, - SlapReply *rs, struct berval *query_uuid ) { @@ -2290,5 +2278,5 @@ while ( cm->cur_entries > (cm->max_entries) ) { BER_BVZERO( &crp_uuid ); - remove_query_and_data( op_tmp, rs, cm, &crp_uuid ); + remove_query_and_data( op_tmp, cm, &crp_uuid ); } @@ -2399,5 +2387,5 @@ switch ( si->caching_reason ) { case PC_POSITIVE: - cache_entries( op, rs, &qc->q_uuid ); + cache_entries( op, &qc->q_uuid ); if ( si->pbi ) si->pbi->bi_cq = qc; @@ -3496,5 +3484,5 @@ return_val = 0; else - return_val = remove_query_data(op, &rs, &query->q_uuid); + return_val = remove_query_data(op, &query->q_uuid); Debug( pcache_debug, "STALE QUERY REMOVED, SIZE=%d\n", return_val, 0, 0 ); Index: servers/slapd/overlays/refint.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/refint.c,v retrieving revision 1.45 diff -u -2 -r1.45 refint.c --- servers/slapd/overlays/refint.c 4 Jun 2009 23:25:35 -0000 1.45 +++ servers/slapd/overlays/refint.c 15 Dec 2009 16:40:54 -0000 @@ -589,5 +589,5 @@ for ( dp = rq->attrs; dp; dp = dp->next ) { Operation op2 = *op; - SlapReply rs2 = { 0 }; + SlapReply rs2 = { REP_RESULT }; refint_attrs *ra; Modifications *m; @@ -605,5 +605,4 @@ } - rs2.sr_type = REP_RESULT; for ( ra = dp->attrs; ra; ra = ra->next ) { size_t len; Index: servers/slapd/overlays/retcode.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/retcode.c,v retrieving revision 1.40 diff -u -2 -r1.40 retcode.c --- servers/slapd/overlays/retcode.c 22 Nov 2009 10:57:17 -0000 1.40 +++ servers/slapd/overlays/retcode.c 15 Dec 2009 16:40:54 -0000 @@ -166,5 +166,8 @@ rs->sr_err = send_search_entry( op, rs ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags = 0; rs->sr_entry = NULL; + rs->sr_attrs = NULL; switch ( rs->sr_err ) { Index: servers/slapd/overlays/sssvlv.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/sssvlv.c,v retrieving revision 1.12 diff -u -2 -r1.12 sssvlv.c --- servers/slapd/overlays/sssvlv.c 29 Sep 2009 01:10:03 -0000 1.12 +++ servers/slapd/overlays/sssvlv.c 15 Dec 2009 16:40:54 -0000 @@ -480,4 +480,5 @@ rs->sr_flags = REP_ENTRY_MUSTRELEASE; rs->sr_err = send_search_entry( op, rs ); + rs_replace_entry( op, rs, NULL, NULL ); if ( rs->sr_err == LDAP_UNAVAILABLE ) break; @@ -519,4 +520,5 @@ rs->sr_flags = REP_ENTRY_MUSTRELEASE; rs->sr_err = send_search_entry( op, rs ); + rs_replace_entry( op, rs, NULL, NULL ); if ( rs->sr_err == LDAP_UNAVAILABLE ) break; Index: servers/slapd/overlays/syncprov.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/syncprov.c,v retrieving revision 1.307 diff -u -2 -r1.307 syncprov.c --- servers/slapd/overlays/syncprov.c 23 Nov 2009 21:17:25 -0000 1.307 +++ servers/slapd/overlays/syncprov.c 15 Dec 2009 16:40:54 -0000 @@ -1411,5 +1411,5 @@ Modifications mod; Operation opm; - SlapReply rsm = { 0 }; + SlapReply rsm = {REP_RESULT}; slap_callback cb = {0}; BackendDB be; Index: servers/slapd/overlays/translucent.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/translucent.c,v retrieving revision 1.67 diff -u -2 -r1.67 translucent.c --- servers/slapd/overlays/translucent.c 29 Nov 2009 18:53:01 -0000 1.67 +++ servers/slapd/overlays/translucent.c 15 Dec 2009 16:40:54 -0000 @@ -817,12 +817,5 @@ re = tavl_delete( &tc->list, le, entry_dn_cmp ); if ( re ) { - if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { - rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; - overlay_entry_release_ov( op, rs->sr_entry, 0, on ); - } - if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { - rs->sr_flags ^= REP_ENTRY_MUSTBEFREED; - entry_free( rs->sr_entry ); - } + rs_flush_entry( op, rs, on ); rc = test_filter( op, re, tc->orig ); if ( rc == LDAP_COMPARE_TRUE ) { @@ -857,12 +850,5 @@ if ( rc == LDAP_SUCCESS && le ) { re = entry_dup( rs->sr_entry ); - if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { - rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; - overlay_entry_release_ov( op, rs->sr_entry, 0, on ); - } - if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { - rs->sr_flags ^= REP_ENTRY_MUSTBEFREED; - entry_free( rs->sr_entry ); - } + rs_flush_entry( op, rs, on ); } else { le = NULL; @@ -904,12 +890,5 @@ /* Dispose of local entry */ if ( tc->step & LCL_SIDE ) { - if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { - rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; - overlay_entry_release_ov( op, rs->sr_entry, 0, on ); - } - if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { - rs->sr_flags ^= REP_ENTRY_MUSTBEFREED; - entry_free( rs->sr_entry ); - } + rs_flush_entry(op, rs, on); } else { overlay_entry_release_ov(op, le, 0, on); @@ -1159,16 +1138,18 @@ av = tavl_end( tc.list, TAVL_DIR_LEFT ); while ( av ) { + rs->sr_flags = REP_ENTRY_MUSTBEFREED; rs->sr_entry = av->avl_data; + av = tavl_next( av, TAVL_DIR_RIGHT ); rc = test_filter( op, rs->sr_entry, op->ors_filter ); if ( rc == LDAP_COMPARE_TRUE ) { - rs->sr_flags = REP_ENTRY_MUSTBEFREED; rc = send_search_entry( op, rs ); - if ( rc ) break; - } else { + if ( rc ) av = NULL; + } + if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { entry_free( rs->sr_entry ); } - av = tavl_next( av, TAVL_DIR_RIGHT ); } tavl_free( tc.list, NULL ); + rs->sr_flags = 0; rs->sr_entry = NULL; } Index: servers/slapd/overlays/valsort.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/valsort.c,v retrieving revision 1.27 diff -u -2 -r1.27 valsort.c --- servers/slapd/overlays/valsort.c 8 Dec 2009 19:53:39 -0000 1.27 +++ servers/slapd/overlays/valsort.c 15 Dec 2009 16:40:54 -0000 @@ -298,4 +298,8 @@ if ( !a ) continue; + /* + * TODO: Why does valsort want the entry to be freeable? + * Modifiable entries need not be - e.g. they can be on the stack. + */ if (( rs->sr_flags & ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) != ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) Index: servers/slapd/overlays/rwm.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/overlays/rwm.c,v retrieving revision 1.122 diff -u -2 -r1.122 rwm.c --- servers/slapd/overlays/rwm.c 8 Dec 2009 18:36:10 -0000 1.122 +++ servers/slapd/overlays/rwm.c 15 Dec 2009 16:40:54 -0000 @@ -891,4 +891,5 @@ rc = LDAP_SUCCESS; } + RS_ASSERT( rc == LDAP_SUCCESS && *ep == rs.sr_entry && rs.sr_flags & REP_ENTRY_MUSTRELEASE ); /* otherwise we should free/release it and/or set *ep = NULL, right? */ } @@ -1505,17 +1506,17 @@ (void)rwm_attrs( op, rs, &e->e_attrs, 1 ); - if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { + if ( e != rs->sr_entry ) { + rs_replace_entry( op, rs, on, e ); + rs->sr_flags = flags; + } else if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { /* ITS#6423: REP_ENTRY_MUSTRELEASE incompatible * with REP_ENTRY_MODIFIABLE */ - if ( rs->sr_entry == e ) { + RS_ASSERT( 0 ); rc = 1; goto fail; - } - - overlay_entry_release_ov( op, rs->sr_entry, 0, on ); } - rs->sr_entry = e; - rs->sr_flags = flags; + RS_ASSERT( rs->sr_entry == e ); + RS_ASSERT( rs->sr_flags == flags ); return SLAP_CB_CONTINUE; Index: servers/slapd/slapi/slapi_pblock.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/slapi/slapi_pblock.c,v retrieving revision 1.79 diff -u -2 -r1.79 slapi_pblock.c --- servers/slapd/slapi/slapi_pblock.c 25 Jul 2009 22:14:16 -0000 1.79 +++ servers/slapd/slapi/slapi_pblock.c 15 Dec 2009 16:40:54 -0000 @@ -1177,11 +1177,5 @@ case SLAPI_SEARCH_RESULT_ENTRY: PBLOCK_ASSERT_OP( pb, 0 ); - if ( pb->pb_rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { - entry_free( pb->pb_rs->sr_entry ); - } else if ( pb->pb_rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { - be_entry_release_r( pb->pb_op, pb->pb_rs->sr_entry ); - pb->pb_rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; - } - pb->pb_rs->sr_entry = (Slapi_Entry *)value; + rs_replace_entry( pb->pb_op, pb->pb_rs, NULL, (Slapi_Entry *)value ); pb->pb_rs->sr_flags |= REP_ENTRY_MUSTBEFREED; break;