]> git.sur5r.net Git - openldap/blobdiff - libraries/liblber/io.c
check for overflows
[openldap] / libraries / liblber / io.c
index 730d05d4fdf350fb05432031bf917d754b3f2060..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;
 
-               errno = 0;
-               sblen=ber_int_sb_read( sb, ber->ber_rwptr,
-                       ((char *)&ber->ber_len + LENSIZE*2 - 1)-ber->ber_rwptr);
+               /* The tag & len can be at most 9 bytes; we try to read up to 8 here */
+               sock_errset(0);
+               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;
 
@@ -529,16 +551,16 @@ ber_get_next(
                                                break;
                                        /* Is the tag too big? */
                                        if (i == sizeof(ber_tag_t)-1) {
-                                               errno = ERANGE;
+                                               sock_errset(ERANGE);
                                                return LBER_DEFAULT;
                                        }
                                }
                                /* Did we run out of bytes? */
                                if ((char *)p == ber->ber_rwptr) {
 #if defined( EWOULDBLOCK )
-                                       errno = EWOULDBLOCK;
+                                       sock_errset(EWOULDBLOCK);
 #elif defined( EAGAIN )
-                                       errno = EAGAIN;
+                                       sock_errset(EAGAIN);
 #endif                 
                                        return LBER_DEFAULT;
                                }
@@ -549,9 +571,9 @@ ber_get_next(
 
                if ( ber->ber_ptr == ber->ber_rwptr ) {
 #if defined( EWOULDBLOCK )
-                       errno = EWOULDBLOCK;
+                       sock_errset(EWOULDBLOCK);
 #elif defined( EAGAIN )
-                       errno = EAGAIN;
+                       sock_errset(EAGAIN);
 #endif                 
                        return LBER_DEFAULT;
                }
@@ -561,16 +583,16 @@ ber_get_next(
                        int i;
                        unsigned char *p = (unsigned char *)ber->ber_ptr;
                        int llen = *p++ & 0x7f;
-                       if (llen > (int)sizeof(ber_len_t)) {
-                               errno = ERANGE;
+                       if (llen > LENSIZE) {
+                               sock_errset(ERANGE);
                                return LBER_DEFAULT;
                        }
                        /* Not enough bytes? */
                        if (ber->ber_rwptr - (char *)p < llen) {
 #if defined( EWOULDBLOCK )
-                               errno = EWOULDBLOCK;
+                               sock_errset(EWOULDBLOCK);
 #elif defined( EAGAIN )
-                               errno = EAGAIN;
+                               sock_errset(EAGAIN);
 #endif                 
                                return LBER_DEFAULT;
                        }
@@ -601,7 +623,7 @@ ber_get_next(
 
                /* make sure length is reasonable */
                if ( ber->ber_len == 0 ) {
-                       errno = ERANGE;
+                       sock_errset(ERANGE);
                        return LBER_DEFAULT;
                }
 
@@ -609,7 +631,7 @@ ber_get_next(
                        ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug,
                                "ber_get_next: sockbuf_max_incoming exceeded "
                                "(%ld > %ld)\n", ber->ber_len, sb->sb_max_incoming );
-                       errno = ERANGE;
+                       sock_errset(ERANGE);
                        return LBER_DEFAULT;
                }
 
@@ -620,7 +642,7 @@ ber_get_next(
                         * already read.
                         */
                        if ( ber->ber_len < sblen + l ) {
-                               errno = ERANGE;
+                               sock_errset(ERANGE);
                                return LBER_DEFAULT;
                        }
                        ber->ber_buf = (char *) ber_memalloc_x( ber->ber_len + 1, ber->ber_memctx );
@@ -652,16 +674,16 @@ ber_get_next(
                to_go = ber->ber_end - ber->ber_rwptr;
                assert( to_go > 0 );
                
-               errno = 0;
+               sock_errset(0);
                res = ber_int_sb_read( sb, ber->ber_rwptr, to_go );
                if (res<=0) return LBER_DEFAULT;
                ber->ber_rwptr+=res;
                
                if (res<to_go) {
 #if defined( EWOULDBLOCK )
-                       errno = EWOULDBLOCK;
+                       sock_errset(EWOULDBLOCK);
 #elif defined( EAGAIN )
-                       errno = EAGAIN;
+                       sock_errset(EAGAIN);
 #endif                 
                        return LBER_DEFAULT;
                }