From f0a151142223b016ef9717db3afb9259ee377481 Mon Sep 17 00:00:00 2001 From: Hallvard Furuseth Date: Wed, 9 May 2007 22:59:04 +0000 Subject: [PATCH] Make ldap_int_thread_userctx_t.ltu_key[] a proper NULL-terminated array. (setkey/getkey expected that, but purgekey could set a NULL in the middle.) Added some checks for input key!=NULL. API changes, need review - I'm not sure what's indented here: - setkey(data=NULL, kfree!=NULL) searched as if intended to reset the key, but updated by setting the key. Now always updates. - setkey(key=, data=NULL) could return either success or failure. Now succeeds iff (data == NULL && kfree == NULL). --- libraries/libldap_r/tpool.c | 63 +++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/libraries/libldap_r/tpool.c b/libraries/libldap_r/tpool.c index 1a62f3f0f9..5171d35bf1 100644 --- a/libraries/libldap_r/tpool.c +++ b/libraries/libldap_r/tpool.c @@ -823,7 +823,7 @@ int ldap_pvt_thread_pool_getkey( ldap_int_thread_userctx_t *ctx = xctx; int i; - if ( !ctx || !data ) return EINVAL; + if ( !ctx || !key || !data ) return EINVAL; for ( i=0; iltu_key[i].ltk_key; i++ ) { if ( ctx->ltu_key[i].ltk_key == key ) { @@ -835,6 +835,18 @@ int ldap_pvt_thread_pool_getkey( return ENOENT; } +static void +clear_key_idx( ldap_int_thread_userctx_t *ctx, int i ) +{ + int j = i; + while ( ++j < MAXKEYS && ctx->ltu_key[j].ltk_key ); + if ( --j != i ) { + ctx->ltu_key[i] = ctx->ltu_key[j]; + i = j; + } + ctx->ltu_key[i].ltk_key = NULL; +} + int ldap_pvt_thread_pool_setkey( void *xctx, void *key, @@ -842,34 +854,30 @@ int ldap_pvt_thread_pool_setkey( ldap_pvt_thread_pool_keyfree_t *kfree ) { ldap_int_thread_userctx_t *ctx = xctx; - int i; + int i, found; if ( !ctx || !key ) return EINVAL; - for ( i=0; iltu_key[i].ltk_key ) || ctx->ltu_key[i].ltk_key == key ) { - if ( data || kfree ) { - ctx->ltu_key[i].ltk_key = key; - ctx->ltu_key[i].ltk_data = data; - ctx->ltu_key[i].ltk_free = kfree; - } else { - int j; - for ( j=i+1; jltu_key[j].ltk_key ) break; - j--; - if ( j != i ) { - ctx->ltu_key[i].ltk_key = ctx->ltu_key[j].ltk_key; - ctx->ltu_key[i].ltk_data = ctx->ltu_key[j].ltk_data; - ctx->ltu_key[i].ltk_free = ctx->ltu_key[j].ltk_free; - } - ctx->ltu_key[j].ltk_key = NULL; - ctx->ltu_key[j].ltk_data = NULL; - ctx->ltu_key[j].ltk_free = NULL; - } - return 0; + for ( i=found=0; iltu_key[i].ltk_key == key ) { + found = 1; + break; + } else if ( !ctx->ltu_key[i].ltk_key ) { + break; } } - return ENOMEM; + + if ( data || kfree ) { + if ( i>=MAXKEYS ) + return ENOMEM; + ctx->ltu_key[i].ltk_key = key; + ctx->ltu_key[i].ltk_data = data; + ctx->ltu_key[i].ltk_free = kfree; + } else if ( found ) { + clear_key_idx( ctx, i ); + } + + return 0; } /* Free all elements with this key, no matter which thread they're in. @@ -880,16 +888,17 @@ void ldap_pvt_thread_pool_purgekey( void *key ) int i, j; ldap_int_thread_userctx_t *ctx; + assert ( key != NULL ); + for ( i=0; iltu_key[j].ltk_key; j++ ) { if ( ctx->ltu_key[j].ltk_key == key ) { if (ctx->ltu_key[j].ltk_free) ctx->ltu_key[j].ltk_free( ctx->ltu_key[j].ltk_key, ctx->ltu_key[j].ltk_data ); - ctx->ltu_key[j].ltk_key = NULL; - ctx->ltu_key[j].ltk_free = NULL; + clear_key_idx( ctx, j ); break; } } -- 2.39.5