From 80b5255f5c42747557578890d1b2f96d4817da47 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Wed, 3 Jun 2009 01:03:45 +0000
Subject: [PATCH] ITS#6159

---
 CHANGES                    |  1 +
 servers/slapd/bconfig.c    | 30 ++++++++++++++++++++++++++++++
 servers/slapd/limits.c     | 21 ++++++++++++++-------
 servers/slapd/proto-slap.h |  2 ++
 4 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/CHANGES b/CHANGES
index 22ea83b96d..9eeab43495 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,7 @@ OpenLDAP 2.4.17 Engineering
 	Fixed slapd global alloc handling (ITS#6054)
 	Fixed slapd moduleload with static backends and modules (ITS#6016)
 	Fixed slapd normalization of updated schema attributes (ITS#5540)
+	Fixed slapd olcLimits handling (ITS#6159)
 	Fixed slapd pagedresults stacked control with overlays (ITS#6056)
 	Fixed slapd password-hash incorrect limit on arg length (ITS#6139)
 	Fixed slapd readonly restrictions (ITS#6109)
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index fae59ceb3b..37c4ff6f3c 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -1385,6 +1385,36 @@ config_generic(ConfigArgs *c) {
 
 		case CFG_LIMITS:
 			/* FIXME: there is no limits_free function */
+			if ( c->valx < 0 ) {
+				limits_destroy( c->be->be_limits );
+				c->be->be_limits = NULL;
+
+			} else {
+				int cnt, num = -1;
+
+				if ( c->be->be_limits ) {
+					for ( num = 0; c->be->be_limits[ num ]; num++ )
+						/* just count */ ;
+				}
+
+				if ( c->valx >= num ) {
+					return 1;
+				}
+
+				if ( num == 1 ) {
+					limits_destroy( c->be->be_limits );
+					c->be->be_limits = NULL;
+
+				} else {
+					limits_free_one( c->be->be_limits[ c->valx ] );
+
+					for ( cnt = c->valx; cnt < num; cnt++ ) {
+						c->be->be_limits[ cnt ] = c->be->be_limits[ cnt + 1 ];
+					}
+				}
+			}
+			break;
+
 		case CFG_ATOPT:
 			/* FIXME: there is no ad_option_free function */
 		case CFG_ROOTDSE:
diff --git a/servers/slapd/limits.c b/servers/slapd/limits.c
index 796149c4b3..cf22aed463 100644
--- a/servers/slapd/limits.c
+++ b/servers/slapd/limits.c
@@ -1324,6 +1324,19 @@ limits_check( Operation *op, SlapReply *rs )
 	return 0;
 }
 
+void
+limits_free_one( 
+	struct slap_limits	*lm )
+{
+	if ( ( lm->lm_flags & SLAP_LIMITS_MASK ) == SLAP_LIMITS_REGEX )
+		regfree( &lm->lm_regex );
+
+	if ( !BER_BVISNULL( &lm->lm_pat ) )
+		ch_free( lm->lm_pat.bv_val );
+
+	ch_free( lm );
+}
+
 void
 limits_destroy( 
 	struct slap_limits	**lm )
@@ -1335,13 +1348,7 @@ limits_destroy(
 	}
 
 	for ( i = 0; lm[ i ]; i++ ) {
-		if ( (lm[ i ]->lm_flags & SLAP_LIMITS_MASK) == SLAP_LIMITS_REGEX )
-			regfree( &lm[ i ]->lm_regex );
-
-		if ( !BER_BVISNULL( &lm[ i ]->lm_pat ) )
-			ch_free( lm[ i ]->lm_pat.bv_val );
-
-		ch_free( lm[ i ] );
+		limits_free_one( lm[ i ] );
 	}
 
 	ch_free( lm );
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index afa95ac91f..982fb8d0ff 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -1144,6 +1144,8 @@ LDAP_SLAPD_F (int) limits_unparse_one LDAP_P((
 	struct slap_limits_set *limit, int which, struct berval *bv, ber_len_t buflen ));
 LDAP_SLAPD_F (int) limits_unparse LDAP_P(( 
 	struct slap_limits *limit, struct berval *bv, ber_len_t buflen ));
+LDAP_SLAPD_F (void) limits_free_one LDAP_P(( 
+	struct slap_limits	*lm ));
 LDAP_SLAPD_F (void) limits_destroy LDAP_P(( struct slap_limits **lm ));
 
 /*
-- 
GitLab