]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/pcache.c
check for NULL backend (ITS#6490)
[openldap] / servers / slapd / overlays / pcache.c
index 309a192771ae367fbc8e2f9bc2056fe7b0f50a96..78c6bed9aecb4866b42be57b2232ce3b064fda41 100644 (file)
@@ -768,6 +768,10 @@ url2query(
                }
                query.scope = lud->lud_scope;
                query.filter = str2filter( lud->lud_filter );
+               if ( query.filter == NULL ) {
+                       rc = -1;
+                       goto error;
+               }
 
                tempstr.bv_val = ch_malloc( strlen( lud->lud_filter ) + 1 );
                tempstr.bv_len = 0;
@@ -823,6 +827,7 @@ static int
 merge_entry(
        Operation               *op,
        Entry                   *e,
+       int                     dup,
        struct berval*          query_uuid )
 {
        int             rc;
@@ -836,6 +841,8 @@ merge_entry(
 
        slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
 
+       if ( dup )
+               e = entry_dup( e );
        attr = e->e_attrs;
        e->e_attrs = NULL;
 
@@ -877,7 +884,7 @@ merge_entry(
                }
        } else {
                if ( op->ora_e == e )
-                       be_entry_release_w( op, e );
+                       entry_free( e );
                rc = 1;
        }
 
@@ -2285,7 +2292,7 @@ cache_entries(
                        remove_query_and_data( op_tmp, rs, cm, &crp_uuid );
                }
 
-               return_val = merge_entry(op_tmp, e, query_uuid);
+               return_val = merge_entry(op_tmp, e, 0, query_uuid);
                ldap_pvt_thread_mutex_lock(&cm->cache_mutex);
                cm->cur_entries += return_val;
                Debug( pcache_debug,
@@ -2471,7 +2478,14 @@ pcache_response(
                        } else if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED
                                && si->qtemp->limitttl )
                        {
+                               Entry *e;
+
                                si->caching_reason = PC_SIZELIMIT;
+                               for (;si->head; si->head=e) {
+                                       e = si->head->e_private;
+                                       si->head->e_private = NULL;
+                                       entry_free(si->head);
+                               }
                        }
 
                } else if ( si->qtemp->negttl && !si->count && !si->over &&
@@ -2630,7 +2644,14 @@ pc_bind_attrs( Operation *op, Entry *e, QueryTemplate *temp,
        }
        *p2 = '\0';
        op->o_tmpfree( vals, op->o_tmpmemctx );
-       return str2filter_x( op, fbv->bv_val );
+
+       /* FIXME: are we sure str2filter_x can't fail?
+        * caller needs to check */
+       {
+               Filter *f = str2filter_x( op, fbv->bv_val );
+               assert( f != NULL );
+               return f;
+       }
 }
 
 /* Check if the requested entry is from the cache and has a valid
@@ -2997,14 +3018,24 @@ pcache_op_search(
                                pbi->bi_cq = answerable;
 
                        op->o_bd = &cm->db;
-#if 0
                        if ( cm->response_cb == PCACHE_RESPONSE_CB_TAIL ) {
+                               slap_callback cb;
                                /* The cached entry was already processed by any
                                 * other overlays, so don't let it get processed again.
+                                *
+                                * This loop removes over_back_response from the stack.
                                 */
-                               op->o_callback = NULL;
+                               if ( overlay_callback_after_backover( op, &cb, 0) == 0 ) {
+                                       slap_callback **scp;
+                                       for ( scp = &op->o_callback; *scp != NULL;
+                                               scp = &(*scp)->sc_next ) {
+                                               if ( (*scp)->sc_next == &cb ) {
+                                                       *scp = cb.sc_next;
+                                                       break;
+                                               }
+                                       }
+                               }
                        }
-#endif
                        i = cm->db.bd_info->bi_op_search( op, rs );
                }
                ldap_pvt_thread_rdwr_runlock(&answerable->rwlock);
@@ -3190,7 +3221,7 @@ refresh_merge( Operation *op, SlapReply *rs )
                        /* No local entry, just add it. FIXME: we are not checking
                         * the cache entry limit here
                         */
-                        merge_entry( op, rs->sr_entry, &ri->ri_q->q_uuid );
+                        merge_entry( op, rs->sr_entry, 1, &ri->ri_q->q_uuid );
                } else {
                        /* Entry exists, update it */
                        Entry ne;
@@ -4489,7 +4520,7 @@ pcache_db_open2(
                        AttributeAssertion      ava = ATTRIBUTEASSERTION_INIT;
                        AttributeName   attrs[ 2 ] = {{{ 0 }}};
 
-                       connection_fake_init( &conn, &opbuf, thrctx );
+                       connection_fake_init2( &conn, &opbuf, thrctx, 0 );
                        op = &opbuf.ob_op;
 
                        op->o_bd = &cm->db;
@@ -4675,7 +4706,7 @@ pcache_db_close(
 
                thrctx = ldap_pvt_thread_pool_context();
 
-               connection_fake_init( &conn, &opbuf, thrctx );
+               connection_fake_init2( &conn, &opbuf, thrctx, 0 );
                op = &opbuf.ob_op;
 
                if ( qm->templates != NULL ) {
@@ -5080,6 +5111,10 @@ pcache_exop_query_delete(
        op->o_req_dn = op->o_req_ndn;
 
        op->o_bd = select_backend( &op->o_req_ndn, 0 );
+       if ( op->o_bd == NULL ) {
+               send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT,
+                       "no global superior knowledge" );
+       }
        rs->sr_err = backend_check_restrictions( op, rs,
                (struct berval *)&pcache_exop_QUERY_DELETE );
        if ( rs->sr_err != LDAP_SUCCESS ) {
@@ -5198,6 +5233,20 @@ pcache_op_extended( Operation *op, SlapReply *rs )
        return SLAP_CB_CONTINUE;
 }
 
+static int
+pcache_entry_release( Operation  *op, Entry *e, int rw )
+{
+       slap_overinst   *on = (slap_overinst *)op->o_bd->bd_info;
+       cache_manager   *cm = on->on_bi.bi_private;
+       BackendDB *db = op->o_bd;
+       int rc;
+
+       op->o_bd = &cm->db;
+       rc = be_entry_release_rw( op, e, rw );
+       op->o_bd = db;
+       return rc;
+}
+
 #ifdef PCACHE_MONITOR
 
 static int
@@ -5584,6 +5633,7 @@ pcache_initialize()
 #endif /* PCACHE_CONTROL_PRIVDB */
        pcache.on_bi.bi_extended = pcache_op_extended;
 
+       pcache.on_bi.bi_entry_release_rw = pcache_entry_release;
        pcache.on_bi.bi_chk_controls = pcache_chk_controls;
 
        pcache.on_bi.bi_cf_ocs = pcocs;