diff --git a/libraries/liblber/decode.c b/libraries/liblber/decode.c
index 68463774248b921cc5939bbf85acea0c4d45ec39..d2fbcdd357176865399775363121f520cc54e5d7 100644
--- a/libraries/liblber/decode.c
+++ b/libraries/liblber/decode.c
@@ -137,6 +137,11 @@ ber_skip_tag( BerElement *ber, ber_len_t *len )
 		*len = lc;
 	}
 
+	/* BER element should have enough data left */
+	if( *len > ber_pvt_ber_remaining( ber ) ) {
+		return LBER_DEFAULT;
+	}
+
 	return tag;
 }
 
@@ -252,7 +257,9 @@ ber_get_stringb(
 	if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
 		return LBER_DEFAULT;
 	}
-	if ( datalen > (*len - 1) ) {
+
+	/* must fit within allocated space with termination */
+	if ( datalen >= *len ) {
 		return LBER_DEFAULT;
 	}
 
diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c
index 1e78515c4c9b3ac5a7add9d5a50f7044428b4aa3..b04edb7890e468a8c36db002994ac448f45e1aea 100644
--- a/libraries/liblber/io.c
+++ b/libraries/liblber/io.c
@@ -77,7 +77,7 @@ ber_read(
 
 	assert( BER_VALID( ber ) );
 
-	nleft = ber->ber_end - ber->ber_ptr;
+	nleft = ber_pvt_ber_remaining( ber );
 	actuallen = nleft < len ? nleft : len;
 
 	AC_MEMCPY( buf, ber->ber_ptr, actuallen );
@@ -524,15 +524,25 @@ get_lenbyte:
 		ber->ber_rwptr += res;
 
 		/* convert length. */
-		ber->ber_len = 0;
 		for( to_go = 0; to_go < res ; to_go++ ) {
 			ber->ber_len <<= 8;
 			ber->ber_len |= netlen[to_go];
 		}
+		if (PTR_IN_VAR(ber->ber_rwptr, ber->ber_len))
+			return LBER_DEFAULT;
 	}
 
 fill_buffer:	
 	/* now fill the buffer. */
+
+	/* make sure length is reasonable */
+	if ( ber->ber_len == 0 ||
+		( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ))
+	{
+		errno = ERANGE;
+		return LBER_DEFAULT;
+	}
+
 	if (ber->ber_buf==NULL) {
 		ber->ber_buf = (char *) LBER_MALLOC( ber->ber_len );
 		if (ber->ber_buf==NULL) {
diff --git a/libraries/liblber/lber-int.h b/libraries/liblber/lber-int.h
index 00a8f06a6caf0d98e03b2efc5bf7eddcb90f903c..ef34dfeb7d10427c50745b2398bb31df4e1d632f 100644
--- a/libraries/liblber/lber-int.h
+++ b/libraries/liblber/lber-int.h
@@ -74,6 +74,7 @@ struct sockbuf {
 	ber_socket_t		sb_fd;
    	unsigned int		sb_trans_needs_read:1;
    	unsigned int		sb_trans_needs_write:1;
+	ber_len_t			sb_max_incoming;
 };
 
 #define SOCKBUF_VALID( sb )	( (sb)->sb_valid == LBER_VALID_SOCKBUF )
diff --git a/libraries/liblber/sockbuf.c b/libraries/liblber/sockbuf.c
index 07627ba85c633fe24ededadabd63c8353c6cc0a2..bb3eb64c74ae8bc5cd40aa100aee0692615d5a17 100644
--- a/libraries/liblber/sockbuf.c
+++ b/libraries/liblber/sockbuf.c
@@ -21,6 +21,10 @@
 #include <io.h>
 #endif /* HAVE_IO_H */
 
+#if defined( HAVE_FCNTL_H )
+#include <fcntl.h>
+#endif
+
 #if defined( HAVE_SYS_FILIO_H )
 #include <sys/filio.h>
 #elif defined( HAVE_SYS_IOCTL_H )
@@ -69,6 +73,7 @@ ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
 	int			ret = 0;
 
 	assert( sb != NULL );
+	assert( SOCKBUF_VALID( sb ) );
 
 	switch ( opt ) {
 		case LBER_SB_OPT_HAS_IO:
@@ -120,6 +125,18 @@ ber_sockbuf_ctrl( Sockbuf *sb, int opt, void *arg )
 			ret = ( sb->sb_trans_needs_write ? 1 : 0 );
 			break;
 
+		case LBER_SB_OPT_GET_MAX_INCOMING:
+			if ( arg != NULL ) {
+				*((ber_len_t *)arg) = sb->sb_max_incoming;
+			}
+			ret = 1;
+			break;
+
+		case LBER_SB_OPT_SET_MAX_INCOMING:
+			sb->sb_max_incoming = *((ber_len_t *)arg);
+			ret = 1;
+			break;
+
 		default:
 			ret = sb->sb_iod->sbiod_io->sbi_ctrl( sb->sb_iod,
 				opt, arg );