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

Heap corruption bug in encode.c (ITS#479)



To:    openldap-its@OpenLDAP.org
Kudos to Dave Steck for the find and fix

There is a situation where ber_put_seqorset() writes a few bytes beyond an allocated buffer, causing a nasty heap corruption bug that makes you crash at some random later time.

The problem occurs when:
	a) You're encoding something like [V] .
	b) You specify NULL for V.
  and	c) The internal buffer of the BerElement is within a few bytes of the end

This type of encoding is used when removing all values of an attribute type, for example.

The '[' code causes the pointer into the buffer to be incremented a few bytes, but it doesn't write anything.  It can actually be incremented beyond the end of the buffer and that's OK.  When you actually do the ber_write, it reallocs the buffer if necessary.

However, if the V is NULL, no ber_write occurs.  When it sees the ']' code, it updates the tag and length fields, which may now be off the end of the buffer.

The solution is to check for this condition in ber_put_seqorset(), and realloc the buffer if necessary before writing into those fields.  We also had to make ber_realloc non-static and move the prototype into lber-int.h.

_______________________________________

diff -r1.1 encode.c
582a583
> 		ber_len_t extend_len;
583a585,596
> 		/* Check if sos_ptr has exceeded buffer.  This can happen with [V]
> 		   for example if the ptr was close to the end of the buffer
> 		   and no data was written for the 'V'.  If so, we must do a realloc
> 		   before doing the SAFEMEMCPY's, which write into the tag and
> 		   length fields.
> 		*/
> 		if ( ber->ber_sos->sos_ptr > ber->ber_end ) {
> 			extend_len = ber->ber_sos->sos_ptr - ber->ber_end;
> 			if ( ber_realloc( ber, extend_len ) != 0 )
> 				return( -1 );
> 		}
>