X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblber%2Fio.c;h=a62161495ab8fca8145953d6feca905341368279;hb=f2958fe7ef5185f879aab3fd057717733f9635b3;hp=d18f861633d966a5580701feaef3a5afb44bd9a3;hpb=fcf97e84486e1159c0f57114e3b130cf49d7f89d;p=openldap diff --git a/libraries/liblber/io.c b/libraries/liblber/io.c index d18f861633..a62161495a 100644 --- a/libraries/liblber/io.c +++ b/libraries/liblber/io.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2009 The OpenLDAP Foundation. + * Copyright 1998-2012 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,7 +55,6 @@ ber_skip_data( ber_len_t actuallen, nleft; assert( ber != NULL ); - assert( LBER_VALID( ber ) ); nleft = ber_pvt_ber_remaining( ber ); @@ -66,6 +65,10 @@ ber_skip_data( return( (ber_slen_t) actuallen ); } +/* + * Read from the ber buffer. The caller must maintain ber->ber_tag. + * Do not use to read whole tags. See ber_get_tag() and ber_skip_data(). + */ ber_slen_t ber_read( BerElement *ber, @@ -76,7 +79,6 @@ ber_read( assert( ber != NULL ); assert( buf != NULL ); - assert( LBER_VALID( ber ) ); nleft = ber_pvt_ber_remaining( ber ); @@ -89,49 +91,54 @@ ber_read( return( (ber_slen_t) actuallen ); } +/* + * Write to the ber buffer. + * Note that ber_start_seqorset/ber_put_seqorset() bypass ber_write(). + */ ber_slen_t ber_write( BerElement *ber, LDAP_CONST char *buf, ber_len_t len, - int nosos ) + int zero ) /* nonzero is unsupported from OpenLDAP 2.4.18 */ { + char **p; + assert( ber != NULL ); assert( buf != NULL ); - assert( LBER_VALID( ber ) ); - if ( nosos || ber->ber_sos == NULL ) { - if ( ber->ber_ptr + len > ber->ber_end ) { - if ( ber_realloc( ber, len ) != 0 ) return( -1 ); - } - AC_MEMCPY( ber->ber_ptr, buf, (size_t)len ); - ber->ber_ptr += len; - return( (ber_slen_t) len ); + if ( zero != 0 ) { + ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug, "%s", + "ber_write: nonzero 4th argument not supported\n" ); + return( -1 ); + } - } else { - if ( ber->ber_sos->sos_ptr + len > ber->ber_end ) { - if ( ber_realloc( ber, len ) != 0 ) return( -1 ); - } - AC_MEMCPY( ber->ber_sos->sos_ptr, buf, (size_t)len ); - ber->ber_sos->sos_ptr += len; - ber->ber_sos->sos_clen += len; - return( (ber_slen_t) len ); + p = ber->ber_sos_ptr == NULL ? &ber->ber_ptr : &ber->ber_sos_ptr; + if ( len > (ber_len_t) (ber->ber_end - *p) ) { + if ( ber_realloc( ber, len ) != 0 ) return( -1 ); } + AC_MEMCPY( *p, buf, len ); + *p += len; + + return( (ber_slen_t) len ); } +/* Resize the ber buffer */ int ber_realloc( BerElement *ber, ber_len_t len ) { - ber_len_t total; - Seqorset *s; - long off; - char *oldbuf; + ber_len_t total, offset, sos_offset; + char *buf; assert( ber != NULL ); - assert( len > 0 ); assert( LBER_VALID( ber ) ); + /* leave room for ber_flatten() to \0-terminate ber_buf */ + if ( ++len == 0 ) { + return( -1 ); + } + total = ber_pvt_ber_total( ber ); #define LBER_EXBUFSIZ 4060 /* a few words less than 2^N for binary buddy */ @@ -140,7 +147,7 @@ ber_realloc( BerElement *ber, ber_len_t len ) /* don't realloc by small amounts */ total += len < LBER_EXBUFSIZ ? LBER_EXBUFSIZ : len; # else - { /* not sure what value this adds */ + { /* not sure what value this adds. reduce fragmentation? */ ber_len_t have = (total + (LBER_EXBUFSIZE - 1)) / LBER_EXBUFSIZ; ber_len_t need = (len + (LBER_EXBUFSIZ - 1)) / LBER_EXBUFSIZ; total = ( have + need ) * LBER_EXBUFSIZ; @@ -150,54 +157,38 @@ ber_realloc( BerElement *ber, ber_len_t len ) total += len; /* realloc just what's needed */ #endif - oldbuf = ber->ber_buf; - - ber->ber_buf = (char *) ber_memrealloc_x( oldbuf, total, ber->ber_memctx ); - - if ( ber->ber_buf == NULL ) { - ber->ber_buf = oldbuf; + if ( total < len || total > (ber_len_t)-1 / 2 /* max ber_slen_t */ ) { return( -1 ); } - ber->ber_end = ber->ber_buf + total; + buf = ber->ber_buf; + offset = ber->ber_ptr - buf; + sos_offset = ber->ber_sos_ptr ? ber->ber_sos_ptr - buf : 0; + /* if ber_sos_ptr != NULL, it is > ber_buf so that sos_offset > 0 */ - /* - * If the stinking thing was moved, we need to go through and - * reset all the sos and ber pointers. Offsets would've been - * a better idea... oh well. - */ - - if ( ber->ber_buf != oldbuf ) { - ber->ber_ptr = ber->ber_buf + (ber->ber_ptr - oldbuf); - - for ( s = ber->ber_sos; s != NULL; s = s->sos_next ) { - off = s->sos_first - oldbuf; - s->sos_first = ber->ber_buf + off; - - off = s->sos_ptr - oldbuf; - s->sos_ptr = ber->ber_buf + off; - } + buf = (char *) ber_memrealloc_x( buf, total, ber->ber_memctx ); + if ( buf == NULL ) { + return( -1 ); } + ber->ber_buf = buf; + ber->ber_end = buf + total; + ber->ber_ptr = buf + offset; + if ( sos_offset ) + ber->ber_sos_ptr = buf + sos_offset; + return( 0 ); } void ber_free_buf( BerElement *ber ) { - Seqorset *s, *next; - assert( LBER_VALID( ber ) ); if ( ber->ber_buf) ber_memfree_x( ber->ber_buf, ber->ber_memctx ); - for( s = ber->ber_sos ; s != NULL ; s = next ) { - next = s->sos_next; - ber_memfree_x( s, ber->ber_memctx ); - } - ber->ber_buf = NULL; - ber->ber_sos = NULL; + ber->ber_sos_ptr = NULL; ber->ber_valid = LBER_UNINITIALIZED; } @@ -230,7 +221,6 @@ ber_flush2( Sockbuf *sb, BerElement *ber, int freeit ) assert( sb != NULL ); assert( ber != NULL ); - assert( SOCKBUF_VALID( sb ) ); assert( LBER_VALID( ber ) ); @@ -244,7 +234,7 @@ ber_flush2( Sockbuf *sb, BerElement *ber, int freeit ) "ber_flush2: %ld bytes to sd %ld%s\n", towrite, (long) sb->sb_fd, ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" ); - ber_log_bprint( LDAP_DEBUG_PACKETS, sb->sb_debug, + ber_log_bprint( LDAP_DEBUG_BER, sb->sb_debug, ber->ber_rwptr, towrite ); } @@ -405,6 +395,10 @@ int ber_flatten2( bv->bv_val = NULL; bv->bv_len = 0; + } else if ( ber->ber_sos_ptr != NULL ) { + /* unmatched "{" and "}" */ + return -1; + } else { /* copy the berval */ ber_len_t len = ber_pvt_ber_write( ber ); @@ -415,10 +409,13 @@ int ber_flatten2( return -1; } AC_MEMCPY( bv->bv_val, ber->ber_buf, len ); - } else { + bv->bv_val[len] = '\0'; + } else if ( ber->ber_buf != NULL ) { bv->bv_val = ber->ber_buf; + bv->bv_val[len] = '\0'; + } else { + bv->bv_val = ""; } - bv->bv_val[len] = '\0'; bv->bv_len = len; } return 0; @@ -484,7 +481,6 @@ ber_get_next( assert( sb != NULL ); assert( len != NULL ); assert( ber != NULL ); - assert( SOCKBUF_VALID( sb ) ); assert( LBER_VALID( ber ) ); @@ -557,11 +553,7 @@ ber_get_next( } /* Did we run out of bytes? */ if ((char *)p == ber->ber_rwptr) { -#if defined( EWOULDBLOCK ) sock_errset(EWOULDBLOCK); -#elif defined( EAGAIN ) - sock_errset(EAGAIN); -#endif return LBER_DEFAULT; } } @@ -570,11 +562,7 @@ ber_get_next( } if ( ber->ber_ptr == ber->ber_rwptr ) { -#if defined( EWOULDBLOCK ) sock_errset(EWOULDBLOCK); -#elif defined( EAGAIN ) - sock_errset(EAGAIN); -#endif return LBER_DEFAULT; } @@ -589,11 +577,7 @@ ber_get_next( } /* Not enough bytes? */ if (ber->ber_rwptr - (char *)p < llen) { -#if defined( EWOULDBLOCK ) sock_errset(EWOULDBLOCK); -#elif defined( EAGAIN ) - sock_errset(EAGAIN); -#endif return LBER_DEFAULT; } for (i=0; iber_rwptr+=res; if (resber_rwptr = NULL; - ber->ber_sos = NULL; + ber->ber_sos_ptr = NULL; ber->ber_end = ber->ber_ptr; ber->ber_ptr = ber->ber_buf; +#if 0 /* TODO: Should we add this? */ + ber->ber_tag = LBER_DEFAULT; + ber->ber_usertag = 0; +#endif } int