Blob Blame Raw
From 254ba1f6adf1575f5992ccc1a228ecd10ce96cc5 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Fri, 12 Dec 2014 15:41:36 -0800
Subject: [PATCH 45/53] Ticket #47960 - cookie_change_info returns random
 negative number if there was no change in a tree

Description: An additional fix for the type mismatch for the change
numbers.  Change Number is declared as "unsigned long" in the Retro
Changelog plugin, while cookie_change_info in the Content Sync plugin
is "int", which could end up with a negative number when the change
number passes (2^31 - 1).

Changing the type of cookie_change_info to "unsigned long".

https://fedorahosted.org/389/ticket/47960

Reviewed by rmeggins@redhat.com and tbordaz@redhat.com (Thank you,
Rich and Thierry!!)

(cherry picked from commit 96c130b432ce0b15028e325c0e337679291aef9f)
(cherry picked from commit 61a4e7035742612a1a8bf42b16e93cc55776dc31)
---
 ldap/servers/plugins/sync/sync.h         |  9 +++--
 ldap/servers/plugins/sync/sync_refresh.c | 32 +++++++++++++-----
 ldap/servers/plugins/sync/sync_util.c    | 56 ++++++++++++++++++++------------
 3 files changed, 65 insertions(+), 32 deletions(-)

diff --git a/ldap/servers/plugins/sync/sync.h b/ldap/servers/plugins/sync/sync.h
index 0bcec7a..803c656 100644
--- a/ldap/servers/plugins/sync/sync.h
+++ b/ldap/servers/plugins/sync/sync.h
@@ -64,10 +64,12 @@
 #define CL_ATTR_NEWSUPERIOR "newsuperior"
 #define CL_SRCH_BASE "cn=changelog"
 
+#define SYNC_INVALID_CHANGENUM ((unsigned long)-1)
+
 typedef struct sync_cookie {
 	char *cookie_client_signature;
 	char *cookie_server_signature;
-	int cookie_change_info;
+	unsigned long cookie_change_info;
 } Sync_Cookie;
 
 typedef struct sync_update {
@@ -80,8 +82,8 @@ typedef struct sync_update {
 
 typedef struct sync_callback {
 	Slapi_PBlock *orig_pb;
-	int changenr;
-	int change_start;
+	unsigned long changenr;
+	unsigned long change_start;
 	int cb_err;
 	Sync_UpdateNode *cb_updates;
 } Sync_CallBackData;
@@ -112,6 +114,7 @@ int sync_cookie_isvalid (Sync_Cookie *testcookie, Sync_Cookie *refcookie);
 void sync_cookie_free (Sync_Cookie **freecookie);
 char * sync_cookie2str(Sync_Cookie *cookie);
 int sync_number2int(char *nrstr);
+unsigned long sync_number2ulong(char *nrstr);
 char *sync_nsuniqueid2uuid(const char *nsuniqueid);
 
 int sync_is_active (Slapi_Entry *e, Slapi_PBlock *pb);
diff --git a/ldap/servers/plugins/sync/sync_refresh.c b/ldap/servers/plugins/sync/sync_refresh.c
index 4e256e6..bfff77b 100644
--- a/ldap/servers/plugins/sync/sync_refresh.c
+++ b/ldap/servers/plugins/sync/sync_refresh.c
@@ -293,9 +293,9 @@ sync_refresh_update_content(Slapi_PBlock *pb, Sync_Cookie *client_cookie, Sync_C
 	cb_data.orig_pb = pb;
 	cb_data.change_start = client_cookie->cookie_change_info;
 
-	filter = slapi_ch_smprintf("(&(changenumber>=%d)(changenumber<=%d))",
-					client_cookie->cookie_change_info,
-					server_cookie->cookie_change_info);
+	filter = slapi_ch_smprintf("(&(changenumber>=%lu)(changenumber<=%lu))",
+	                           client_cookie->cookie_change_info,
+	                           server_cookie->cookie_change_info);
 	slapi_search_internal_set_pb(
 		seq_pb, 
 		CL_SRCH_BASE,
@@ -305,7 +305,7 @@ sync_refresh_update_content(Slapi_PBlock *pb, Sync_Cookie *client_cookie, Sync_C
 		0,
 		NULL, NULL, 
 		plugin_get_default_component_id(),
-		0);							  
+		0);
 
 	rc = slapi_search_internal_callback_pb (
 		seq_pb, &cb_data, NULL, sync_read_entry_from_changelog, NULL);
@@ -460,6 +460,7 @@ sync_read_entry_from_changelog( Slapi_Entry *cl_entry, void *cb_data)
 	int chg_req;
 	int prev = 0;
 	int index = 0;
+	unsigned long chgnum = 0;
 	Sync_CallBackData *cb = (Sync_CallBackData *) cb_data;
 
 	if (cb == NULL) {
@@ -470,13 +471,28 @@ sync_read_entry_from_changelog( Slapi_Entry *cl_entry, void *cb_data)
 	if (uniqueid == NULL) {
 		slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, 
 			"Retro Changelog does not provied nsuniquedid."
-			"Check RCL plugin configuration." );
+			"Check RCL plugin configuration.\n" );
 		return(1);
 	}
-	chgtype = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_CHGTYPE);
 	chgnr = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_CHANGENUMBER);
-
-	index = sync_number2int(chgnr) - cb->change_start;
+	chgnum = sync_number2ulong(chgnr);
+	if (SYNC_INVALID_CHANGENUM == chgnum) {
+		slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, 
+			"Change number provided by Retro Changelog is invalid: %s\n", chgnr);
+		slapi_ch_free_string(&chgnr);
+		slapi_ch_free_string(&uniqueid);
+		return(1);
+	}
+	if (chgnum < cb->change_start) {
+		slapi_log_error (SLAPI_LOG_FATAL, SYNC_PLUGIN_SUBSYSTEM, 
+			"Change number provided by Retro Changelog %s is less than the initial number %lu\n",
+			chgnr, cb->change_start);
+		slapi_ch_free_string(&chgnr);
+		slapi_ch_free_string(&uniqueid);
+		return(1);
+	}
+	index = chgnum - cb->change_start;
+	chgtype = sync_get_attr_value_from_entry (cl_entry, CL_ATTR_CHGTYPE);
 	chg_req = sync_str2chgreq(chgtype);
 	switch (chg_req){ 
 		case LDAP_REQ_ADD:
diff --git a/ldap/servers/plugins/sync/sync_util.c b/ldap/servers/plugins/sync/sync_util.c
index af22bcb..67cb453 100644
--- a/ldap/servers/plugins/sync/sync_util.c
+++ b/ldap/servers/plugins/sync/sync_util.c
@@ -266,10 +266,10 @@ sync_cookie2str(Sync_Cookie *cookie)
 	char *cookiestr = NULL;
 
 	if (cookie) {
-		cookiestr = slapi_ch_smprintf("%s#%s#%d",
-				cookie->cookie_server_signature,
-				cookie->cookie_client_signature,
-				cookie->cookie_change_info);
+		cookiestr = slapi_ch_smprintf("%s#%s#%lu",
+		                               cookie->cookie_server_signature,
+		                               cookie->cookie_client_signature,
+		                               cookie->cookie_change_info);
 	}
 	return(cookiestr);
 }
@@ -370,10 +370,11 @@ sync_handle_cnum_entry(Slapi_Entry *e, void *cb_data)
 			slapi_attr_first_value( chattr,&sval );
 			if ( NULL != sval ) {
 				value = slapi_value_get_berval ( sval );
-				if( NULL != value && NULL != value->bv_val &&
-					'\0' != value->bv_val[0]) {
-					cb->changenr = sync_number2int(value->bv_val);
-					cb->cb_err = 0; /* changenr successfully set */
+				if (value && value->bv_val && ('\0' != value->bv_val[0])) {
+					cb->changenr = sync_number2ulong(value->bv_val);
+					if (SYNC_INVALID_CHANGENUM != cb->changenr) {
+						cb->cb_err = 0; /* changenr successfully set */
+					}
 				}
 			}
 		}
@@ -452,31 +453,30 @@ sync_cookie_get_client_info(Slapi_PBlock *pb)
 	clientinfo = slapi_ch_smprintf("%s:%s:%s",clientdn,targetdn,strfilter);
 	return (clientinfo);
 }
-static int
+static unsigned long
 sync_cookie_get_change_number(int lastnr, const char *uniqueid)
 {
 	Slapi_PBlock *srch_pb;
 	Slapi_Entry **entries;
 	Slapi_Entry *cl_entry;
 	int rv;
-	int newnr = -1;
+	unsigned long newnr = SYNC_INVALID_CHANGENUM;
 	char *filter = slapi_ch_smprintf("(&(changenumber>=%d)(targetuniqueid=%s))",lastnr,uniqueid);
 
 	srch_pb = slapi_pblock_new();
-    	slapi_search_internal_set_pb(srch_pb, CL_SRCH_BASE,
-           				LDAP_SCOPE_SUBTREE, filter,
-            				NULL, 0, NULL, NULL, plugin_get_default_component_id(), 0);
- 	slapi_search_internal_pb(srch_pb);
+	slapi_search_internal_set_pb(srch_pb, CL_SRCH_BASE, LDAP_SCOPE_SUBTREE, filter,
+	                             NULL, 0, NULL, NULL, plugin_get_default_component_id(), 0);
+	slapi_search_internal_pb(srch_pb);
 	slapi_pblock_get(srch_pb, SLAPI_PLUGIN_INTOP_RESULT, &rv);
-	if ( rv == LDAP_SUCCESS) {
+	if (rv == LDAP_SUCCESS) {
 		slapi_pblock_get(srch_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
-    		if (entries && *entries) {
+		if (entries && *entries) {
 			Slapi_Attr *attr;
 			Slapi_Value *val;
 			cl_entry = *entries; /* only use teh first one */
 			slapi_entry_attr_find(cl_entry, CL_ATTR_CHANGENUMBER, &attr);
 			slapi_attr_first_value(attr, &val);
-			newnr = sync_number2int((char *)slapi_value_get_string(val));
+			newnr = sync_number2ulong((char *)slapi_value_get_string(val));
 		}
 	}
 
@@ -579,8 +579,8 @@ sync_cookie_parse (char *cookie)
 		if (p) {
 			*p = '\0';
 			sc->cookie_client_signature = slapi_ch_strdup(q);
-			sc->cookie_change_info = sync_number2int(p+1);
-			if (sc->cookie_change_info < 0) {
+			sc->cookie_change_info = sync_number2ulong(p+1);
+			if (SYNC_INVALID_CHANGENUM == sc->cookie_change_info) {
 				goto error_return;
 			}
 		} else {
@@ -716,14 +716,28 @@ sync_pblock_copy(Slapi_PBlock *src)
 	return dest;
 }
 
-int sync_number2int(char *chgnrstr)
+int
+sync_number2int(char *chgnrstr)
 {
 	char *end;
 	int nr;
-	nr = strtoul(chgnrstr, &end, 10);
+	nr = (int)strtoul(chgnrstr, &end, 10);
 	if ( *end == '\0') {
 		return (nr);
 	} else {
 		return (-1);
 	}
 }
+
+unsigned long
+sync_number2ulong(char *chgnrstr)
+{
+	char *end;
+	unsigned long nr;
+	nr = strtoul(chgnrstr, &end, 10);
+	if ( *end == '\0') {
+		return (nr);
+	} else {
+		return SYNC_INVALID_CHANGENUM;
+	}
+}
-- 
1.9.3