Diff for /libraries/liblber/encode.c between versions 1.72 and 1.73

version 1.72, 2009/07/29 13:06:28 version 1.73, 2009/07/29 14:49:42
Line 1 Line 1
 /* encode.c - ber output encoding routines */  /* encode.c - ber output encoding routines */
 /* $OpenLDAP: pkg/ldap/libraries/liblber/encode.c,v 1.71 2009/01/21 23:40:19 kurt Exp $ */  /* $OpenLDAP: pkg/ldap/libraries/liblber/encode.c,v 1.72 2009/07/29 13:06:28 hallvard Exp $ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.  /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *   *
  * Copyright 1998-2009 The OpenLDAP Foundation.   * Copyright 1998-2009 The OpenLDAP Foundation.
Line 31 Line 31
 #include "portable.h"  #include "portable.h"
   
 #include <ctype.h>  #include <ctype.h>
   #include <limits.h>
 #include <stdio.h>  #include <stdio.h>
   
 #include <ac/stdlib.h>  #include <ac/stdlib.h>
Line 41 Line 42
   
 #include "lber-int.h"  #include "lber-int.h"
   
 static int ber_put_len LDAP_P((  
         BerElement *ber,  
         ber_len_t len,  
         int nosos ));  
   
 static int ber_start_seqorset LDAP_P((  
         BerElement *ber,  
         ber_tag_t tag ));  
   
 static int ber_put_seqorset LDAP_P(( BerElement *ber ));  #define OCTET_SIZE(type) ((ber_len_t) (sizeof(type)*CHAR_BIT + 7) / 8)
   #define TAGBUF_SIZE OCTET_SIZE(ber_tag_t)
   #define LENBUF_SIZE (1 + OCTET_SIZE(ber_len_t))
   #define HEADER_SIZE (TAGBUF_SIZE + LENBUF_SIZE)
   
 static int ber_put_int_or_enum LDAP_P((  /*
         BerElement *ber,   * BER element size constrains:
         ber_int_t num,   *
         ber_tag_t tag ));   * - We traditionally support a length of max 0xffffffff.  However
    *   some functions return an int length so that is their max.
    *   MAXINT_BERSIZE is the max for those functions.
    *
    * - MAXINT_BERSIZE must fit in MAXINT_BERSIZE_OCTETS octets.
    *
    * - sizeof(ber_elem_size_t) is normally MAXINT_BERSIZE_OCTETS:
    *   Big enough for MAXINT_BERSIZE, but not more.  (Larger wastes
    *   space in the working encoding and DER encoding of a sequence
    *   or set.  Smaller further limits sizes near a sequence/set.)
    *
    * ber_len_t is mostly unrelated to this.  Which may be for the best,
    * since it is also used for lengths of data that are never encoded.
    */
   #define MAXINT_BERSIZE \
           (INT_MAX>0xffffffffUL ? (ber_len_t) 0xffffffffUL : INT_MAX-HEADER_SIZE)
   #define MAXINT_BERSIZE_OCTETS 4
   typedef ber_uint_t ber_elem_size_t; /* normally 32 bits */
   
 #define BER_TOP_BYTE(type)      (sizeof(type)-1)  
 #define BER_TOP_MASK(type)      ((type)0xffU << (BER_TOP_BYTE(type)*8))  
   
 static int  /* Prepend tag to ptr, which points to the end of a tag buffer */
 ber_calc_taglen( ber_tag_t tag )  static unsigned char *
   ber_prepend_tag( unsigned char *ptr, ber_tag_t tag )
 {  {
         int     i = BER_TOP_BYTE(ber_tag_t);          do {
         ber_tag_t       mask = BER_TOP_MASK(ber_tag_t);                  *--ptr = (unsigned char) tag & 0xffU;
           } while ( (tag >>= 8) != 0 );
         /* find the first non-all-zero byte in the tag */  
         for ( ; i > 0; i-- ) {  
                 /* not all zero */  
                 if ( tag & mask ) break;  
                 mask >>= 8;  
         }  
   
         return i + 1;          return ptr;
 }  }
   
 static int  /* Prepend ber length to ptr, which points to the end of a length buffer */
 ber_put_tag(  static unsigned char *
         BerElement      *ber,  ber_prepend_len( unsigned char *ptr, ber_len_t len )
         ber_tag_t tag,  
         int nosos )  
 {  
         int rc;  
         int taglen;  
         int     i;  
         unsigned char nettag[sizeof(ber_tag_t)];  
   
         assert( ber != NULL );  
         assert( LBER_VALID( ber ) );  
   
         taglen = ber_calc_taglen( tag );  
   
         for( i=taglen-1; i>=0; i-- ) {  
                 nettag[i] = (unsigned char)(tag & 0xffU);  
                 tag >>= 8;  
         }  
   
         rc = ber_write( ber, (char *) nettag, taglen, nosos );  
   
         return rc;  
 }  
   
 static ber_len_t  
 ber_calc_lenlen( ber_len_t len )  
 {  {
         /*          /*
          * short len if it's less than 128 - one byte giving the len,           * short len if it's less than 128 - one byte giving the len,
          * with bit 8 0.           * with bit 8 0.
          */  
   
         if ( len <= (ber_len_t) 0x7FU ) return 1;  
   
         /*  
          * long len otherwise - one byte with bit 8 set, giving the           * long len otherwise - one byte with bit 8 set, giving the
          * length of the length, followed by the length itself.           * length of the length, followed by the length itself.
          */           */
   
         if ( len <= (ber_len_t) 0xffU ) return 2;          *--ptr = (unsigned char) len & 0xffU;
         if ( len <= (ber_len_t) 0xffffU ) return 3;  
         if ( len <= (ber_len_t) 0xffffffU ) return 4;  
   
         return 5;  
 }  
   
 static int  
 ber_put_len( BerElement *ber, ber_len_t len, int nosos )  
 {  
         int rc;  
         int             i,j;  
         char            lenlen;  
         ber_len_t       mask;  
         unsigned char netlen[sizeof(ber_len_t)];  
   
         assert( ber != NULL );          if ( len >= 0x80 ) {
         assert( LBER_VALID( ber ) );                  unsigned char *endptr = ptr--;
   
         /*                  while ( (len >>= 8) != 0 ) {
          * short len if it's less than 128 - one byte giving the len,                          *ptr-- = (unsigned char) len & 0xffU;
          * with bit 8 0.                  }
          */                  *ptr = (unsigned char) (endptr - ptr) + 0x80U;
   
         if ( len <= 127 ) {  
                 char length_byte = (char) len;  
                 return ber_write( ber, &length_byte, 1, nosos );  
         }  
   
         /*  
          * long len otherwise - one byte with bit 8 set, giving the  
          * length of the length, followed by the length itself.  
          */  
   
         /* find the first non-all-zero byte */  
         i = BER_TOP_BYTE(ber_len_t);  
         mask = BER_TOP_MASK(ber_len_t);  
         for ( ; i > 0; i-- ) {  
                 /* not all zero */  
                 if ( len & mask ) break;  
                 mask >>= 8;  
         }  
         lenlen = (unsigned char) ++i;  
         if ( lenlen > 4 ) return -1;  
   
         lenlen |= 0x80UL;  
   
         /* write the length of the length */  
         if ( ber_write( ber, &lenlen, 1, nosos ) != 1 ) return -1;  
   
         for( j=i-1; j>=0; j-- ) {  
                 netlen[j] = (unsigned char)(len & 0xffU);  
                 len >>= 8;  
         }          }
   
         /* write the length itself */          return ptr;
         rc = ber_write( ber, (char *) netlen, i, nosos );  
   
         return rc == i ?  i+1 : -1;  
 }  }
   
 /* out->bv_len should be the buffer size on input */  /* out->bv_len should be the buffer size on input */
Line 210  ber_encode_oid( BerValue *in, BerValue * Line 139  ber_encode_oid( BerValue *in, BerValue *
         for (;;) {          for (;;) {
                 if ( ptr > inend ) return -1;                  if ( ptr > inend ) return -1;
   
                   /* Write the OID component little-endian, then reverse it */
                 len = 0;                  len = 0;
                 do {                  do {
                         der[len++] = (val & 0xff) | 0x80;                          der[len++] = (val & 0xff) | 0x80;
Line 241  ber_put_int_or_enum( Line 171  ber_put_int_or_enum(
         ber_int_t num,          ber_int_t num,
         ber_tag_t tag )          ber_tag_t tag )
 {  {
         int rc;          ber_uint_t unum;
         int     i, j, sign, taglen, lenlen;          unsigned char sign, data[TAGBUF_SIZE+1 + OCTET_SIZE(ber_int_t)], *ptr;
         ber_len_t       len;  
         ber_uint_t      unum, mask;  
         unsigned char netnum[sizeof(ber_uint_t)];  
   
         sign = (num < 0);          sign = 0;
         unum = num;     /* Bit fiddling should be done with unsigned values */          unum = num;     /* Bit fiddling should be done with unsigned values */
           if ( num < 0 ) {
         /*                  sign = 0xffU;
          * high bit is set - look for first non-all-one byte                  unum = ~unum;
          * high bit is clear - look for first non-all-zero byte          }
          */          for ( ptr = &data[sizeof(data) - 1] ;; unum >>= 8 ) {
         i = BER_TOP_BYTE(ber_int_t);                  *ptr-- = (sign ^ (unsigned char) unum) & 0xffU;
         mask = BER_TOP_MASK(ber_uint_t);                  if ( unum < 0x80 )      /* top bit at *ptr is sign bit */
         for ( ; i > 0; i-- ) {                          break;
                 if ( sign ) {  
                         /* not all ones */  
                         if ( (unum & mask) != mask ) break;  
                 } else {  
                         /* not all zero */  
                         if ( unum & mask ) break;  
                 }  
                 mask >>= 8;  
         }  
   
         /*  
          * we now have the "leading byte".  if the high bit on this  
          * byte matches the sign bit, we need to "back up" a byte.  
          */  
         mask = (unum & ((ber_uint_t)0x80U << (i * 8)));  
         if ( (mask && !sign) || (sign && !mask) ) {  
                 i++;  
         }  
   
         len = i + 1;  
   
         if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {  
                 return -1;  
         }  
   
         if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ) {  
                 return -1;  
         }  
         i++;  
   
         for( j=i-1; j>=0; j-- ) {  
                 netnum[j] = (unsigned char)(unum & 0xffU);  
                 unum >>= 8;  
         }          }
   
         rc = ber_write( ber, (char *) netnum, i, 0 );          *ptr = (unsigned char) (&data[sizeof(data) - 1] - ptr); /* length */
           ptr = ber_prepend_tag( ptr, tag );
   
         /* length of tag + length + contents */          return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
         return rc == i ? taglen + lenlen + i : -1;  
 }  }
   
 int  int
Line 331  ber_put_ostring( Line 225  ber_put_ostring(
         ber_len_t len,          ber_len_t len,
         ber_tag_t tag )          ber_tag_t tag )
 {  {
         int taglen, lenlen, rc;          int rc;
           unsigned char header[HEADER_SIZE], *ptr;
   
         if ( tag == LBER_DEFAULT ) {          if ( tag == LBER_DEFAULT ) {
                 tag = LBER_OCTETSTRING;                  tag = LBER_OCTETSTRING;
         }          }
   
         if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 )          if ( len > MAXINT_BERSIZE ) {
                 return -1;                  return -1;
           }
   
         if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ||          ptr = ber_prepend_len( &header[sizeof(header)], len );
                 (ber_len_t) ber_write( ber, str, len, 0 ) != len )          ptr = ber_prepend_tag( ptr, tag );
         {  
                 rc = -1;          rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 );
         } else {          if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) {
                 /* return length of tag + length + contents */                  /* length(tag + length + contents) */
                 rc = taglen + lenlen + len;                  rc += (int) len;
         }          }
   
         return rc;          return rc;
Line 383  ber_put_bitstring( Line 279  ber_put_bitstring(
         ber_len_t blen /* in bits */,          ber_len_t blen /* in bits */,
         ber_tag_t tag )          ber_tag_t tag )
 {  {
         int                             taglen, lenlen;          int rc;
         ber_len_t               len;          ber_len_t               len;
         unsigned char   unusedbits;          unsigned char   unusedbits, header[HEADER_SIZE + 1], *ptr;
   
         if ( tag == LBER_DEFAULT ) {          if ( tag == LBER_DEFAULT ) {
                 tag = LBER_BITSTRING;                  tag = LBER_BITSTRING;
         }          }
   
         if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {          unusedbits = (unsigned char) -blen & 7;
           len = blen / 8 + (unusedbits != 0); /* (blen+7)/8 without overflow */
           if ( len >= MAXINT_BERSIZE ) {
                 return -1;                  return -1;
         }          }
   
         len = ( blen + 7 ) / 8;          header[sizeof(header) - 1] = unusedbits;
         unusedbits = (unsigned char) ((len * 8) - blen);          ptr = ber_prepend_len( &header[sizeof(header) - 1], len + 1 );
         if ( (lenlen = ber_put_len( ber, len + 1, 0 )) == -1 ) {          ptr = ber_prepend_tag( ptr, tag );
                 return -1;  
         }  
   
         if ( ber_write( ber, (char *)&unusedbits, 1, 0 ) != 1 ) {          rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 );
                 return -1;          if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) {
                   /* length(tag + length + unused bit count + bitstring) */
                   rc += (int) len;
         }          }
   
         if ( (ber_len_t) ber_write( ber, str, len, 0 ) != len ) {          return rc;
                 return -1;  
         }  
   
         /* return length of tag + length + unused bit count + contents */  
         return taglen + 1 + lenlen + len;  
 }  }
   
 int  int
 ber_put_null( BerElement *ber, ber_tag_t tag )  ber_put_null( BerElement *ber, ber_tag_t tag )
 {  {
         int     taglen;          unsigned char data[TAGBUF_SIZE + 1], *ptr;
   
         if ( tag == LBER_DEFAULT ) {          if ( tag == LBER_DEFAULT ) {
                 tag = LBER_NULL;                  tag = LBER_NULL;
         }          }
   
         if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {          data[sizeof(data) - 1] = 0;                     /* length */
                 return -1;          ptr = ber_prepend_tag( &data[sizeof(data) - 1], tag );
         }  
   
         if ( ber_put_len( ber, 0, 0 ) != 1 ) {          return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
                 return -1;  
         }  
   
         return taglen + 1;  
 }  }
   
 int  int
Line 439  ber_put_boolean( Line 327  ber_put_boolean(
         ber_int_t boolval,          ber_int_t boolval,
         ber_tag_t tag )          ber_tag_t tag )
 {  {
         int                             taglen;          unsigned char data[TAGBUF_SIZE + 2], *ptr;
         unsigned char   c;  
   
         if ( tag == LBER_DEFAULT )          if ( tag == LBER_DEFAULT )
                 tag = LBER_BOOLEAN;                  tag = LBER_BOOLEAN;
   
         if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) {          data[sizeof(data) - 1] = boolval ? 0xff : 0;
                 return -1;          data[sizeof(data) - 2] = 1;                     /* length */
         }          ptr = ber_prepend_tag( &data[sizeof(data) - 2], tag );
   
         if ( ber_put_len( ber, 1, 0 ) != 1 ) {          return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
                 return -1;  }
         }  
   
         c = boolval ? (unsigned char) ~0U : (unsigned char) 0U;  
   
         if ( ber_write( ber, (char *) &c, 1, 0 ) != 1 ) {  /* Max number of length octets in a sequence or set, normally 5 */
                 return -1;  #define SOS_LENLEN (1 + (sizeof(ber_elem_size_t) > MAXINT_BERSIZE_OCTETS ? \
         }                  (ber_len_t) sizeof(ber_elem_size_t) : MAXINT_BERSIZE_OCTETS))
   
         return taglen + 2;  /* Header of incomplete sequence or set */
 }  typedef struct seqorset_header {
           char xtagbuf[TAGBUF_SIZE + 1];  /* room for tag + len(tag or len) */
 #define FOUR_BYTE_LEN   5          union {
                   ber_elem_size_t offset;         /* enclosing seqence/set */
                   char padding[SOS_LENLEN-1];     /* for final length encoding */
           } next_sos;
   #       define SOS_TAG_END(header) ((unsigned char *) &(header).next_sos - 1)
   } Seqorset_header;
   
   /* Start a sequence or set */
 static int  static int
 ber_start_seqorset(  ber_start_seqorset(
         BerElement *ber,          BerElement *ber,
         ber_tag_t tag )          ber_tag_t tag )
 {  {
         Seqorset        *new;          /*
            * Write the tag and SOS_LENLEN octets reserved for length, to ber.
            * For now, length octets = (tag length, previous ber_sos_inner).
            *
            * Update ber_sos_inner and the write-cursor ber_sos_ptr.  ber_ptr
            * will not move until the outermost sequence or set is complete.
            */
   
           Seqorset_header header;
           unsigned char   *headptr;
           ber_len_t               taglen, headlen;
           char                    *dest, **p;
   
         assert( ber != NULL );          assert( ber != NULL );
         assert( LBER_VALID( ber ) );          assert( LBER_VALID( ber ) );
   
         new = (Seqorset *) ber_memcalloc_x( 1, sizeof(Seqorset), ber->ber_memctx );          if ( ber->ber_sos_ptr == NULL ) {       /* outermost sequence/set? */
                   header.next_sos.offset = 0;
         if ( new == NULL ) {                  p = &ber->ber_ptr;
                 return -1;  
         }  
   
         new->sos_ber = ber;  
         if ( ber->ber_sos == NULL ) {  
                 new->sos_first = ber->ber_ptr;  
         } else {          } else {
                 new->sos_first = ber->ber_sos->sos_ptr;                  if ( (ber_len_t) -1 > (ber_elem_size_t) -1 ) {
                           if ( ber->ber_sos_inner > (ber_elem_size_t) -1 )
                                   return -1;
                   }
                   header.next_sos.offset = ber->ber_sos_inner;
                   p = &ber->ber_sos_ptr;
         }          }
           headptr = ber_prepend_tag( SOS_TAG_END(header), tag );
           *SOS_TAG_END(header) = taglen = SOS_TAG_END(header) - headptr;
           headlen = taglen + SOS_LENLEN;
   
           /* As ber_write(,headptr,headlen,) except update ber_sos_ptr, not *p */
           if ( headlen > (ber_len_t) (ber->ber_end - *p) ) {
                   if ( ber_realloc( ber, headlen ) != 0 )
                           return -1;
           }
           dest = *p;
           AC_MEMCPY( dest, headptr, headlen );
           ber->ber_sos_ptr = dest + headlen;
   
         /* Set aside room for a 4 byte length field */          ber->ber_sos_inner = dest + taglen - ber->ber_buf;
         new->sos_ptr = new->sos_first + ber_calc_taglen( tag ) + FOUR_BYTE_LEN;  
         new->sos_tag = tag;  
   
         new->sos_next = ber->ber_sos;  
         ber->ber_sos = new;  
   
           /*
            * Do not return taglen + SOS_LENLEN here - then ber_put_seqorset()
            * should return lenlen - SOS_LENLEN + len, which can be < 0.
            */
         return 0;          return 0;
 }  }
   
Line 517  ber_start_set( BerElement *ber, ber_tag_ Line 429  ber_start_set( BerElement *ber, ber_tag_
         return ber_start_seqorset( ber, tag );          return ber_start_seqorset( ber, tag );
 }  }
   
   /* End a sequence or set */
 static int  static int
 ber_put_seqorset( BerElement *ber )  ber_put_seqorset( BerElement *ber )
 {  {
         int rc;          Seqorset_header header;
         ber_len_t       len;          unsigned char   *lenptr;        /* length octets in the sequence/set */
         unsigned char netlen[sizeof(ber_len_t)];          ber_len_t               len;            /* length(contents) */
         int                     taglen;          ber_len_t               xlen;           /* len + length(length) */
         ber_len_t       lenlen;  
         unsigned char   ltag = 0x80U + FOUR_BYTE_LEN - 1;  
         Seqorset        *next;  
         Seqorset        **sos = &ber->ber_sos;  
   
         assert( ber != NULL );          assert( ber != NULL );
         assert( LBER_VALID( ber ) );          assert( LBER_VALID( ber ) );
   
         if( *sos == NULL ) return -1;          if ( ber->ber_sos_ptr == NULL ) return -1;
   
         /*  
          * If this is the toplevel sequence or set, we need to actually  
          * write the stuff out.  Otherwise, it's already been put in  
          * the appropriate buffer and will be written when the toplevel  
          * one is written.  In this case all we need to do is update the  
          * length and tag.  
          */  
   
         len = (*sos)->sos_clen;  
   
         if ( sizeof(ber_len_t) > 4 && len > 0xffffffffUL ) {          lenptr = (unsigned char *) ber->ber_buf + ber->ber_sos_inner;
           xlen = ber->ber_sos_ptr - (char *) lenptr;
           if ( xlen > MAXINT_BERSIZE + SOS_LENLEN ) {
                 return -1;                  return -1;
         }          }
   
         if ( ber->ber_options & LBER_USE_DER ) {          /* Extract sequence/set information from length octets */
                 lenlen = ber_calc_lenlen( len );          memcpy( SOS_TAG_END(header), lenptr, SOS_LENLEN );
   
         } else {          /* Store length, and close gap of leftover reserved length octets */
                 lenlen = FOUR_BYTE_LEN;          len = xlen - SOS_LENLEN;
         }          if ( ber->ber_options & LBER_USE_DER ) {
   
         if( lenlen > 1 ) {  
                 int i;                  int i;
                 ber_len_t j = len;                  lenptr[0] = SOS_LENLEN - 1 + 0x80; /* length(length)-1 */
                 for( i=lenlen-2; i >= 0; i-- ) {                  for( i = SOS_LENLEN; --i > 0; len >>= 8 ) {
                         netlen[i] = j & 0xffU;                          lenptr[i] = len & 0xffU;
                         j >>= 8;  
                 }                  }
         } else {          } else {
                 netlen[0] = (unsigned char)(len & 0x7fU);                  unsigned char *p = ber_prepend_len( lenptr + SOS_LENLEN, len );
         }                  ber_len_t unused = p - lenptr;
                   if ( unused != 0 ) {
         if ( (next = (*sos)->sos_next) == NULL ) {                          /* length(length) < the reserved SOS_LENLEN bytes */
                 /* write the tag */                          xlen -= unused;
                 if ( (taglen = ber_put_tag( ber, (*sos)->sos_tag, 1 )) == -1 ) {                          AC_MEMCPY( lenptr, p, xlen );
                         return( -1 );                          ber->ber_sos_ptr = (char *) lenptr + xlen;
                 }                  }
           }
   
                 if ( ber->ber_options & LBER_USE_DER ) {          ber->ber_sos_inner = header.next_sos.offset;
                         /* Write the length in the minimum # of octets */          if ( header.next_sos.offset == 0 ) { /* outermost sequence/set? */
                         if ( ber_put_len( ber, len, 1 ) == -1 ) {  
                                 return -1;  
                         }  
   
                         if (lenlen != FOUR_BYTE_LEN) {  
                                 /*  
                                  * We set aside FOUR_BYTE_LEN bytes for  
                                  * the length field.  Move the data if  
                                  * we don't actually need that much  
                                  */  
                                 AC_MEMCPY( (*sos)->sos_first + taglen +  
                                     lenlen, (*sos)->sos_first + taglen +  
                                     FOUR_BYTE_LEN, len );  
                         }  
                 } else {  
                         /* Fill FOUR_BYTE_LEN bytes for length field */  
                         /* one byte of length length */  
                         if ( ber_write( ber, (char *)&ltag, 1, 1 ) != 1 ) {  
                                 return -1;  
                         }  
   
                         /* the length itself */  
                         rc  = ber_write( ber, (char *) netlen, FOUR_BYTE_LEN-1, 1 );  
   
                         if( rc != FOUR_BYTE_LEN - 1 ) {  
                                 return -1;  
                         }  
                 }  
                 /* The ber_ptr is at the set/seq start - move it to the end */                  /* The ber_ptr is at the set/seq start - move it to the end */
                 (*sos)->sos_ber->ber_ptr += len;                  ber->ber_ptr = ber->ber_sos_ptr;
                   ber->ber_sos_ptr = NULL;
         } else {  
                 int i;  
                 unsigned char nettag[sizeof(ber_tag_t)];  
                 ber_tag_t tmptag = (*sos)->sos_tag;  
   
                 if( ber->ber_sos->sos_ptr > ber->ber_end ) {  
                         /* The sos_ptr exceeds the end of the BerElement  
                          * this can happen, for example, when the sos_ptr  
                          * is near the end and no data was written for the  
                          * 'V'.  We must realloc the BerElement to ensure  
                          * we don't overwrite the buffer when writing  
                          * the tag and length fields.  
                          */  
                         ber_len_t ext = ber->ber_sos->sos_ptr - ber->ber_end;  
   
                         if( ber_realloc( ber,  ext ) != 0 ) {  
                                 return -1;  
                         }  
                 }  
   
                 /* the tag */  
                 taglen = ber_calc_taglen( tmptag );  
   
                 for( i = taglen-1; i >= 0; i-- ) {  
                         nettag[i] = (unsigned char)(tmptag & 0xffU);  
                         tmptag >>= 8;  
                 }  
   
                 AC_FMEMCPY( (*sos)->sos_first, nettag, taglen );  
   
                 if ( ber->ber_options & LBER_USE_DER ) {  
                         ltag = (lenlen == 1)  
                                 ? (unsigned char) len  
                                 : (unsigned char) (0x80U + (lenlen - 1));  
                 }  
   
                 /* one byte of length length */  
                 (*sos)->sos_first[1] = ltag;  
   
                 if ( ber->ber_options & LBER_USE_DER ) {  
                         if (lenlen > 1) {  
                                 /* Write the length itself */  
                                 AC_FMEMCPY( (*sos)->sos_first + 2, netlen, lenlen - 1 );  
                         }  
                         if (lenlen != FOUR_BYTE_LEN) {  
                                 /*  
                                  * We set aside FOUR_BYTE_LEN bytes for  
                                  * the length field.  Move the data if  
                                  * we don't actually need that much  
                                  */  
                                 AC_FMEMCPY( (*sos)->sos_first + taglen +  
                                     lenlen, (*sos)->sos_first + taglen +  
                                     FOUR_BYTE_LEN, len );  
                         }  
                 } else {  
                         /* the length itself */  
                         AC_FMEMCPY( (*sos)->sos_first + taglen + 1,  
                             netlen, FOUR_BYTE_LEN - 1 );  
                 }  
   
                 next->sos_clen += (taglen + lenlen + len);  
                 next->sos_ptr += (taglen + lenlen + len);  
         }          }
   
         /* we're done with this seqorset, so free it up */          return xlen + *SOS_TAG_END(header); /* lenlen + len + taglen */
         ber_memfree_x( (char *) (*sos), ber->ber_memctx );  
         *sos = next;  
   
         return taglen + lenlen + len;  
 }  }
   
 int  int
Line 740  ber_printf( BerElement *ber, LDAP_CONST Line 545  ber_printf( BerElement *ber, LDAP_CONST
                         break;                          break;
   
                 case 'N':       /* Debug NULL */                  case 'N':       /* Debug NULL */
                           rc = 0;
                         if( lber_int_null != 0 ) {                          if( lber_int_null != 0 ) {
                                 /* Insert NULL to ensure peer ignores unknown tags */                                  /* Insert NULL to ensure peer ignores unknown tags */
                                 rc = ber_put_null( ber, lber_int_null );                                  rc = ber_put_null( ber, lber_int_null );
                         } else {  
                                 rc = 0;  
                         }                          }
                         break;                          break;
   

Removed from v.1.72  
changed lines
  Added in v.1.73


______________
© Copyright 1998-2020, OpenLDAP Foundation, info@OpenLDAP.org