]> git.sur5r.net Git - openldap/blobdiff - libraries/liblber/io.c
check for overflows
[openldap] / libraries / liblber / io.c
index b697acee1fb008ef1c0fe6ffa0cabe3616ca9332..4063b26c82360b10c41c1bf18adaaa1bdc0789be 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2008 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "lber-int.h"
 #include "ldap_log.h"
 
+ber_slen_t
+ber_skip_data(
+       BerElement *ber,
+       ber_len_t len )
+{
+       ber_len_t       actuallen, nleft;
+
+       assert( ber != NULL );
+
+       assert( LBER_VALID( ber ) );
+
+       nleft = ber_pvt_ber_remaining( ber );
+       actuallen = nleft < len ? nleft : len;
+       ber->ber_ptr += actuallen;
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
+
+       return( (ber_slen_t) actuallen );
+}
+
 ber_slen_t
 ber_read(
        BerElement *ber,
@@ -185,11 +204,8 @@ ber_free_buf( BerElement *ber )
 void
 ber_free( BerElement *ber, int freebuf )
 {
-#ifdef LDAP_MEMORY_DEBUG
-       assert( ber != NULL );
-#endif
-
        if( ber == NULL ) {
+               LDAP_MEMORY_DEBUG_ASSERT( ber != NULL );
                return;
        }
 
@@ -472,8 +488,10 @@ ber_get_next(
        assert( SOCKBUF_VALID( sb ) );
        assert( LBER_VALID( ber ) );
 
-       ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
-               "ber_get_next\n" );
+       if ( ber->ber_debug & LDAP_DEBUG_TRACE ) {
+               ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
+                       "ber_get_next\n" );
+       }
 
        /*
         * Any ber element looks like this: tag length contents.
@@ -504,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;
 
@@ -561,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;
                        }