[Date Prev][Date Next] [Chronological] [Thread] [Top]

RE: ldapsearch problems (ITS#2490)



This is a multi-part message in MIME format.

------=_NextPart_000_0057_01C31E12.356434B0
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: 7bit

Thanks for this, but it has some obvious problems. Setting errno when read()
returns 0 is incorrect behavior. This will cause ber_get_next() to treat an
EOF/close as a retry.

Also, even if your patch were valid, you have used C++ style comments in it,
which is not acceptable.

  -- Howard Chu
  Chief Architect, Symas Corp.       Director, Highland Sun
  http://www.symas.com               http://highlandsun.com/hyc
  Symas: Premier OpenSource Development and Support 

> -----Original Message-----
> From: Patrick Dreyer, SY-UCP [mailto:Patrick.Dreyer@swisscom-ucp.com]
> Sent: Monday, May 19, 2003 6:55 AM
> To: Howard Chu; peter@adpm.de; openldap-its@OpenLDAP.org
> Subject: RE: ldapsearch problems (ITS#2490)
> 
> 
> > A fix has been committed to CVS HEAD. Please try the 
> attached patch to libraries/liblber/io.c and let us know your results.
> 
> It doesn't :-(
> 
> Below you find my solution for ber_get_next(), which works 
> but is not optimized yet to read multiple bytes at once 
> during reading the tag and length instead reading one after one.
> As you'll see, the big difference is, that if I do not 
> process it as a failure if ber_int_sb_read() returns with 
> zero. And my solution doesn't have any problems to leave and 
> being recalled if no data was currently available.
> 
> Please try my solution and give me some feedpack - only 
> positiv ones are welcome :-))
> 
> Patrick
> 
> ================================================================
> ber_tag_t
> ber_get_next(
>   Sockbuf *sb,
>   ber_len_t *len,
>   BerElement *ber )
> {
>   ber_slen_t sblen;
> 
>   assert( sb != NULL );
>   assert( len != NULL );
>   assert( ber != NULL );
> 
>   assert( SOCKBUF_VALID( sb ) );
>   assert( LBER_VALID( ber ) );
> 
> #ifdef NEW_LOGGING
>   LDAP_LOG( BER, ENTRY, "ber_get_next: enter\n", 0, 0, 0 );
> #else
>   ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
>     "ber_get_next\n" );
> #endif
> 
>   /*
>    * Any ber element looks like this: tag length contents.
>    * Assuming everything's ok, we return the tag byte (we can 
> assume a single
>    * byte), return the length in len, and the rest of the 
> undecoded element in
>    * buf.
>    *
>    * Assumptions:
>    *  1) tag and len at most 32 bits wide
>    *  2) definite lengths
>    *  3) primitive encodings used whenever possible
>    *
>    * The code also handles multi-byte tags. The first few 
> bytes of the message
>    * are read to check for multi-byte tags and lengths. These 
> bytes are
>    * temporarily stored in the ber_tag, ber_len, and 
> ber_usertag fields of the
>    * berelement until tag/len parsing is complete. After this 
> parsing, any
>    * leftover bytes and the rest of the message are copied 
> into the ber_buf.
>    */
> 
>   // we start reading the next element
>   if (ber->ber_rwptr == NULL) {
>     #if 0
>       /* XXYYZ - dtest does like this assert.  */
>       assert( ber->ber_buf == NULL );
>     #endif
>     ber->ber_tag     = 0;
>     ber->ber_usertag = 0;
>     ber->ber_rwptr = (char*)&ber->ber_tag;
>   }
> 
>   // reading tag as long as ber_rwptr points inside ber_tag
>   if ((char*)&ber->ber_tag <= ber->ber_rwptr
>       && ber->ber_rwptr < (char*)&ber->ber_len) {
>     // first byte
>     if (ber->ber_usertag == 0) {
>       sblen = ber_int_sb_read(sb, ber->ber_rwptr, 1);
>       if (sblen <= 0) {
>         if (sblen == 0) {
>           #if defined(EWOULDBLOCK)
>             errno = EWOULDBLOCK;
>           #elif defined(EAGAIN)
>             errno = EAGAIN;
>           #endif      
>         }
>         return LBER_DEFAULT;
>       }
> 
>       // is only one byte long
>       if ((*ber->ber_rwptr & LBER_BIG_TAG_MASK) != 
> LBER_BIG_TAG_MASK) {
>         ber->ber_tag     = *ber->ber_rwptr;
>         ber->ber_usertag = 0;
>         ber->ber_rwptr   = (char*)&ber->ber_len;
>       }
> 
>       // otherwise multi byte
>       else
>         ber->ber_usertag = *ber->ber_rwptr++;
>     } // first byte
> 
>     // more bytes
>     if (ber->ber_usertag != 0) {
>       do {
>         // tag too big
>         if (ber->ber_rwptr == (char*)&ber->ber_len) {
>           #if defined(EWOULDBLOCK)
>             errno = EWOULDBLOCK;
>           #elif defined(EAGAIN)
>             errno = EAGAIN;
>           #endif      
>           return LBER_DEFAULT;
>         }
> 
>         sblen = ber_int_sb_read(sb, ber->ber_rwptr, 1);
>         if (sblen <= 0) {
>           if (sblen == 0) {
>             #if defined(EWOULDBLOCK)
>               errno = EWOULDBLOCK;
>             #elif defined(EAGAIN)
>               errno = EAGAIN;
>             #endif      
>           }
>           return LBER_DEFAULT;
>         }
> 
>         ber->ber_usertag <<= 8;
>         ber->ber_usertag |=  *ber->ber_rwptr;
>       } while((*ber->ber_rwptr++ & LBER_MORE_TAG_MASK) == 
> LBER_MORE_TAG_MASK);
> 
>       ber->ber_tag     = ber->ber_usertag;
>       ber->ber_usertag = 0;
>       ber->ber_rwptr   = (char*)&ber->ber_len;
>     }
>   } // reading tag
> 
>   // reading length as long as ber_rwptr points inside ber_len
>   if ((char*)ber->ber_len <= ber->ber_rwptr
>       && ber->ber_rwptr < (char*)&ber->ber_usertag) {
>     // first byte
>     if (ber->ber_usertag == 0) {
>       sblen = ber_int_sb_read(sb, ber->ber_rwptr, 1);
>       if (sblen <= 0) {
>         if (sblen == 0) {
>           #if defined(EWOULDBLOCK)
>             errno = EWOULDBLOCK;
>           #elif defined(EAGAIN)
>             errno = EAGAIN;
>           #endif      
>         }
>         return LBER_DEFAULT;
>       }
> 
>       // is only one byte long
>       if ((*ber->ber_rwptr & 0x80) == 0) {
>         ber->ber_len     = *ber->ber_rwptr;
>         ber->ber_usertag = 0;
>       }
> 
>       // otherwise multi byte
>       else {
>         ber->ber_usertag = *ber->ber_rwptr++ & 0x7f;
> 
>         // length too big
>         if (ber->ber_usertag > sizeof(ber->ber_len)) {
>           errno = ERANGE;
>           return LBER_DEFAULT;
>         }
>       }
>     } // first byte
> 
>     // more bytes
>     for (; ber->ber_usertag > 0; --ber->ber_usertag, 
> ++ber->ber_rwptr) {
>       char buf;
>       sblen = ber_int_sb_read(sb, &buf, 1);
>       if (sblen <= 0) {
>         if (sblen == 0) {
>           #if defined(EWOULDBLOCK)
>             errno = EWOULDBLOCK;
>           #elif defined(EAGAIN)
>             errno = EAGAIN;
>           #endif      
>         }
>         return LBER_DEFAULT;
>       }
> 
>       ber->ber_len <<= 8;
>       ber->ber_len |=  buf;
>     } // more bytes
> 
>     // be sure we have to read at least one byte of data
>     if (ber->ber_len == 0) {
>       errno = ERANGE;
>       return LBER_DEFAULT;
>     }
> 
>     // be sure sockbuf_max_incoming didn't exceed
>     if  (sb->sb_max_incoming > 0 && ber->ber_len > 
> sb->sb_max_incoming) {
>       #ifdef NEW_LOGGING
>         LDAP_LOG( BER, ERR, 
>           "ber_get_next: sockbuf_max_incoming exceeded "
>           "(%d > %d)\n", ber->ber_len, sb->sb_max_incoming, 0 );
>       #else
>         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 );
>       #endif
>       errno = ERANGE;
>       return LBER_DEFAULT;
>     }
> 
>     ber->ber_rwptr = (char*)&ber->ber_usertag;
>   } // reading length
> 
>   // allocate buffer
>   if (ber->ber_buf == NULL) {
>     ber->ber_buf = LBER_MALLOC(ber->ber_len+1);
>     if (ber->ber_buf == NULL)
>       return LBER_DEFAULT;
> 
>     ber->ber_ptr   = ber->ber_buf;
>     ber->ber_end   = ber->ber_buf + ber->ber_len;
>     ber->ber_rwptr = ber->ber_buf;
>   }
> 
>   // reading data
>   if (ber->ber_buf <= ber->ber_rwptr && ber->ber_rwptr < 
> ber->ber_end) {
>     sblen = ber_int_sb_read(sb, ber->ber_rwptr, ber->ber_end 
> - ber->ber_rwptr);
>     if (sblen <= 0) {
>       if (sblen == 0) {
>         #if defined(EWOULDBLOCK)
>           errno = EWOULDBLOCK;
>         #elif defined(EAGAIN)
>           errno = EAGAIN;
>         #endif      
>       }
>       return LBER_DEFAULT;
>     }
> 
>     ber->ber_rwptr += sblen;
> 
>     // more data
>     if (ber->ber_rwptr < ber->ber_end) {
>       #if defined(EWOULDBLOCK)
>         errno = EWOULDBLOCK;
>       #elif defined(EAGAIN)
>         errno = EAGAIN;
>       #endif      
>       return LBER_DEFAULT;
>     }
> 
>     // whole element is read
>     ber->ber_rwptr = NULL;
>     *len           = ber->ber_len;
> 
>     // dump if debugging is switched on
>     if (ber->ber_debug) {
>       #ifdef NEW_LOGGING
>         LDAP_LOG( BER, DETAIL1, 
>           "ber_get_next: tag 0x%lx len %ld\n", 
>           ber->ber_tag, ber->ber_len, 0  );
>         if (LDAP_LOGS_TEST(BER, DETAIL2))
>           BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 ));
>       #else
>         ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
>           "ber_get_next: tag 0x%lx len %ld contents:\n",
>           ber->ber_tag, ber->ber_len );
>         ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
>       #endif
>     }
> 
>     return ber->ber_tag;
>   }
> 
>   // the ber structure is messed up if we reach this point
>   assert(0);
>   return LBER_DEFAULT;
> } // ber_get_next
> 

------=_NextPart_000_0057_01C31E12.356434B0
Content-Type: application/ms-tnef;
	name="winmail.dat"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
	filename="winmail.dat"

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
r/Ru9S86QPIy/wKfjOofryC+XxDC8PXwQvD/eXFgsgVfE+Gf+yxfLWYkPfwrK+9bMmAEzzK/4zG9
IP/fEWEzBa83jpLxD98YIGoR/yhv4yJjwtGgUPBoQQ4P5i//5zIwPwOvEM8R3xffE/8VD/8WHxcv
Sj8ZTxpfG28dfx6P/xw/Mu4I/woPCx9DXw0fTs7/Dw9cv0f/SQ9PDErfS+9M3/9N72IfT+9nH1Hv
Tuwcz1Ovr1S/Vc82nyzsPP9hOG7ffXGPfO7QKq8xjsLR15BlhyQfOZAlJk1PUkUl2f/nQSa7eVyY
7ykv8fZz/nLt/3P/Lc8u/zAPMR9sTDqE+dn/fD/5mqsV+p/7r9L2/T+EQv9GGv9fAG8Bf4QPPxYD
3zrP/z3vBw8IH1fPWN9Z7wxfXC//XV9eb1+fYK9m72LvY/9lL/9mP6LvaH9RH2q/b29tH24vPzHf
Mu8hnyKvI78kxzB4/jifoZ9/fS6dEipfdf+Af/+Bj6+PMy80PzVPzsK1/7o/57gfeLO1IDdmfC9B
2YnFn0LPQ98/CCcQjBB6Zd4QD0RoRqK1z6OMUkFOR/5FuS+tn66vrF/QLzqPxH/bPK+nqGbUsERQ
O8GfyTH7LeDqYC3WfpuAzPY5kER8/8qv3zCEMbIw7pDPTZjvmfn/9uDukJuPnJ/ar56/4U+g3/+h
76fvpA/mP6Yvpz/m/6lf/6pvq3/QT83/zw+8T4JfjqT/cq+27XUC3A7SNNSv067doLfdEPGAsiB3
siCEMHayIP/GgIkziqCVEHeAirCVELIH98mg6iD9AGGVf7ca4x/Lvx/Mz/Ff8m3zf/sOc29jQmve
8V9tYXjd0WOMb22Jgu6gZG4nlRDwZXhjZeqA/p3gctng/5nhCCvXgZDb4LK86ArfiZCnAK/kouox
IE7lcF/l4DRHR+rwR+1e5bBBUPkQ4iggJ0HfICdQEyHtX1QgIt2iZwOgX7IQePx0OgefCKMJZOqA
FLATr3kUsCgl/OAnEBjg6xBc/G4imongsd8gDf+JkN8gHwwwWo7p0TZfjFRvZ188cHKZocmwElQE
UEJVwSYAQ09OTlOaieowf97w2OAXrxS/Fc8W3xfvbP8Y8ybAGV8abwiFHB/ugwDv/wH/Aw8EHwUv
JXpEfpIff09Phs6JxDAP0lJhbIpgY/f9ALIh3BBm7GCM3I4n3vF1ejJO5aBMk6447HrlQfc6AOXw
ycsr3004rzm2LQ//Lh81zzEag5Y+2u1Ljifugf9ET9mAtvtFXzGLRJ80JkJP/4cK/lw+n47/kN+R
4iV2Riq/k67dL5n/mwhGKyV2LYLd/z2/4I/fn+LP62rkv+XP6+//6A9eKenv6v/sL+0/7m/y399A
f0GPL39I/4M4K3pQVLP/Qj/UOv5fyAqRplL/D35e//9gD2E/Yk9jf2SPZb9mz2f/j2oPax9sL2/+
d2hv/TD5wCFlbX5AlRCxgVXibU/3MZo54mb7KreW65RHGW9PYZQ4ZHVtcLOiIRNn6zUisYFzvmB0
MmAlMbIAf3GPIJt0XxA/EU8SXoCQVPl7IEwxE48ib8ZwwoHEEP0msHjGAicCJ1STj7b42MMfJ7wM
MCnPs5QSZlNfVNBFU1QokqkyypCXD+MS8oCAVU1Qs+AYsHowD1rwVTEngRJkRVZFTP+AgZzTVlPf
IZoAKd8dLx4/5R9LVCygQ0Ugb51PlJ+fla7boLIAsmDd8HM6J1P/pu+YH7cpmh+jx4riH0sTA/+l
/aD3oZ8q/oHff4qsGkuPn0yfviGs4lSgRCB1Y3/xt/2whEGD8HPAUPzgdYsTn/wBVeEyYLjxhEFw
b93h96r4/VDYkihdcK3Zf99CGhfSQyKqt7x9wgAAHgBCEAEAAAAyAAAAPDAwQTY4ODBFQ0ExRDJF
NDVBQ0ZBMUY1NEFGNEVEMzdCMDRBQTkyQG1haWwudWNwPgAAAAMACVkBAAAAAwABbiAAAAALAAGA
CCAGAAAAAADAAAAAAAAARgAAAAADhQAAAAAAAAMAA4AIIAYAAAAAAMAAAAAAAABGAAAAABCFAAAA
AAAAAwAHgAggBgAAAAAAwAAAAAAAAEYAAAAAUoUAACdqAQAeAAmACCAGAAAAAADAAAAAAAAARgAA
AABUhQAAAQAAAAQAAAA5LjAAHgAKgAggBgAAAAAAwAAAAAAAAEYAAAAANoUAAAEAAAABAAAAAAAA
AB4AC4AIIAYAAAAAAMAAAAAAAABGAAAAADeFAAABAAAAAQAAAAAAAAAeAAyACCAGAAAAAADAAAAA
AAAARgAAAAA4hQAAAQAAAAEAAAAAAAAACwANgAggBgAAAAAAwAAAAAAAAEYAAAAAgoUAAAEAAAAL
ADqACCAGAAAAAADAAAAAAAAARgAAAAAOhQAAAAAAAAMAPIAIIAYAAAAAAMAAAAAAAABGAAAAABGF
AAAAAAAAAwA9gAggBgAAAAAAwAAAAAAAAEYAAAAAGIUAAAAAAAALAFKACCAGAAAAAADAAAAAAAAA
RgAAAAAGhQAAAAAAAAMAU4AIIAYAAAAAAMAAAAAAAABGAAAAAAGFAAAAAAAAAgH4DwEAAAAQAAAA
4gzDUzrx3EW9ftMCMP7j+gIB+g8BAAAAEAAAAOIMw1M68dxFvX7TAjD+4/oCAfsPAQAAAIMAAAAA
AAAAOKG7EAXlEBqhuwgAKypWwgAAbXNwc3QuZGxsAAAAAABOSVRB+b+4AQCqADfZbgAAAEQ6XGhv
bWVcaHljXFdJTlxMb2NhbCBTZXR0aW5nc1xBcHBsaWNhdGlvbiBEYXRhXE1pY3Jvc29mdFxPdXRs
b29rXG91dGxvb2sucHN0AAADAP4PBQAAAAMADTT9NwAAAgF/AAEAAAAxAAAAMDAwMDAwMDBFMjBD
QzM1MzNBRjFEQzQ1QkQ3RUQzMDIzMEZFRTNGQTQ0MkE3RjAwAAAAAAMABhDvoZgDAwAHECYWAAAD
ABAQAAAAAAMAERABAAAAHgAIEAEAAABlAAAAVEhBTktTRk9SVEhJUyxCVVRJVEhBU1NPTUVPQlZJ
T1VTUFJPQkxFTVNTRVRUSU5HRVJSTk9XSEVOUkVBRCgpUkVUVVJOUzBJU0lOQ09SUkVDVEJFSEFW
SU9SVEhJU1dJTExDQQAAAADOEQ==

------=_NextPart_000_0057_01C31E12.356434B0--