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

RE: sl_malloc is unportable (ITS#2551)

> -----Original Message-----
> From: owner-openldap-bugs@OpenLDAP.org
> [mailto:owner-openldap-bugs@OpenLDAP.org]On Behalf Of hyc@symas.com

> > -----Original Message-----
> > From: owner-openldap-bugs@OpenLDAP.org
> > [mailto:owner-openldap-bugs@OpenLDAP.org]On Behalf Of
> h.b.furuseth@usit.uio.no
> > Full_Name: Hallvard B Furuseth
> > Version: HEAD
> > OS:
> > URL:
> > Submission from: (NULL) (
> > Submitted by: hallvard
> > This test in sl_realloc() and sl_free() yields undefined behaviour:
> > 	/* Not our memory? */
> > 	if ( !sh || ptr < sh->h_base || ptr >= sh->h_end ) {
> > Also this in sl_release() and sl_context():
> > 	if ( sh && ptr >= sh->h_base && ptr <= sh->h_end ) {
> > The operators < <= > >= are only defined between two
> pointers into the
> > same block of memory.  An example of how they can fail with pointers
> > to different blocks of memory is if a pointer consists of a segment
> > number and an offset into the segment, and an object cannot cross a
> > segment boundary.  Then these operators need only compare
> the offsets,
> > they can ignore the segment numbers.

This is a flaw in the ANSI C specification. It's important not to lose sight
of practical considerations when delving into specs and theoretical
situations. The fact is that at the machine level, a pointer *must* fit in a
machine word. If it is larger than a machine word, then it can only be used
indirectly - i.e., you need a pointer to point to it. This is patently
ridiculous. As such, a compiler gains no performance advantage from
generating code that only compares a portion of a pointer against a portion
of another pointer. Generally this will be more expensive, because while a
single instruction can be used to compare one word to another, multiple
instructions would be required to mask off portions of a word before and
after the comparison.

Note that the objective isn't an ordering comparison here; it would be fine
with me to replace these comparisons with a macro:

	#define SLAP_PTR_WITHIN(a,b,c) ((b)<=(a) && (a)<=(c))
	/* What goes here is up to whoever is unfortunate enough to be porting
	 * to such a broken compiler architecture. Some possibilities:
	 * segment/offset based malloc:
	 *   SEGMENT_OF(a) == SEGMENT_OF(b)
	 * some other bizarre machine:
	 *   memcmp(&a,&b,sizeof(a)) >= 0 && memcmp(&a,&c,sizeof(a)) <= 0)
#error FixMe

Whether the architecture/compiler uses linear memory or not has no bearing on
whether we can or cannot distinguish our TL pointers from any other pointers.

As an aside, whether a system uses linear memory or not also should not have
any effect on the outcome of comparing two arbitrary pointers. At the machine
level, a word is a word is a word is a word.

> > So slapd needs an `#ifdef USE_SL_MALLOC' to be defined for
> > architectures
> > or architecture/compiler combinations where sl_malloc works.
> > Unfortunately I cannot think of a reliable configure test for this,
> > the best I can think of is to collect information about where
> > it works,
> > and hard-code #if tests for that into the code.

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