From f0388223d5ee019fd768f41c71d5f4f80352b031 Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Thu, 10 Jul 2008 01:16:48 +0000
Subject: [PATCH] ITS#5580

---
 CHANGES                    |  1 +
 libraries/liblber/io.c     | 12 ++++++++----
 libraries/libldap/result.c | 17 ++++++++++-------
 3 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/CHANGES b/CHANGES
index 735f81e600..0e80ec19ac 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,7 @@
 OpenLDAP 2.4 Change Log
 
 OpenLDAP 2.4.11 Engineering
+	Fixed liblber ber_get_next length decoding (ITS#5580)
 	Added libldap assertion control (ITS#5560)
 	Fixed libldap GnuTLS CRL result handling (ITS#5577)
 	Fixed slapd crash with no listeners (ITS#5563)
diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c
index a85f081aa4..4063b26c82 100644
--- a/libraries/liblber/io.c
+++ b/libraries/liblber/io.c
@@ -522,14 +522,18 @@ ber_get_next(
 	}
 
 	while (ber->ber_rwptr > (char *)&ber->ber_tag && ber->ber_rwptr <
-		(char *)&ber->ber_len + LENSIZE*2 -1) {
+		(char *)&ber->ber_len + LENSIZE*2) {
 		ber_slen_t sblen;
 		char buf[sizeof(ber->ber_len)-1];
 		ber_len_t tlen = 0;
 
+		/* The tag & len can be at most 9 bytes; we try to read up to 8 here */
 		sock_errset(0);
-		sblen=ber_int_sb_read( sb, ber->ber_rwptr,
-			((char *)&ber->ber_len + LENSIZE*2 - 1)-ber->ber_rwptr);
+		sblen=((char *)&ber->ber_len + LENSIZE*2 - 1)-ber->ber_rwptr;
+		/* Trying to read the last len byte of a 9 byte tag+len */
+		if (sblen<1)
+			sblen = 1;
+		sblen=ber_int_sb_read( sb, ber->ber_rwptr, sblen );
 		if (sblen<=0) return LBER_DEFAULT;
 		ber->ber_rwptr += sblen;
 
@@ -579,7 +583,7 @@ ber_get_next(
 			int i;
 			unsigned char *p = (unsigned char *)ber->ber_ptr;
 			int llen = *p++ & 0x7f;
-			if (llen > (int)sizeof(ber_len_t)) {
+			if (llen > LENSIZE) {
 				sock_errset(ERANGE);
 				return LBER_DEFAULT;
 			}
diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c
index 945176bf4e..25ed78904c 100644
--- a/libraries/libldap/result.c
+++ b/libraries/libldap/result.c
@@ -351,18 +351,20 @@ wait4msg(
 #endif
 
 			if ( !lc_ready ) {
+				int err;
 				rc = ldap_int_select( ld, tvp );
-#ifdef LDAP_DEBUG
 				if ( rc == -1 ) {
+					err = sock_errno();
+#ifdef LDAP_DEBUG
 					Debug( LDAP_DEBUG_TRACE,
 						"ldap_int_select returned -1: errno %d\n",
-						sock_errno(), 0, 0 );
-				}
+						err, 0, 0 );
 #endif
+				}
 
 				if ( rc == 0 || ( rc == -1 && (
 					!LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_RESTART)
-						|| sock_errno() != EINTR ) ) )
+						|| err != EINTR ) ) )
 				{
 					ld->ld_errno = (rc == -1 ? LDAP_SERVER_DOWN :
 						LDAP_TIMEOUT);
@@ -493,7 +495,7 @@ try_read1msg(
 	LDAPRequest	*lr, *tmplr, dummy_lr = { 0 };
 	LDAPConn	*lc;
 	BerElement	tmpber;
-	int		rc, refer_cnt, hadref, simple_request;
+	int		rc, refer_cnt, hadref, simple_request, err;
 	ber_int_t	lderr;
 
 #ifdef LDAP_CONNECTIONLESS
@@ -547,15 +549,16 @@ nextresp3:
 		break;
 
 	case LBER_DEFAULT:
+		err = sock_errno();
 #ifdef LDAP_DEBUG		   
 		Debug( LDAP_DEBUG_CONNS,
 			"ber_get_next failed.\n", 0, 0, 0 );
 #endif		   
 #ifdef EWOULDBLOCK			
-		if ( sock_errno() == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
+		if ( err == EWOULDBLOCK ) return LDAP_MSG_X_KEEP_LOOKING;
 #endif
 #ifdef EAGAIN
-		if ( sock_errno() == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
+		if ( err == EAGAIN ) return LDAP_MSG_X_KEEP_LOOKING;
 #endif
 		ld->ld_errno = LDAP_SERVER_DOWN;
 #ifdef LDAP_R_COMPILE
-- 
GitLab