diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2010-10-30 15:36:33 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2010-10-30 15:36:33 +0000 |
commit | fd05125e3ec4fab9284b606d45a68a018d77627e (patch) | |
tree | 1347446338835bb3641acba17d5c913225255260 /libexec | |
parent | 62811e7f886358e9487f8b47fb1e6cc694d39e28 (diff) |
fix a 10 year old bug in the memory allocator, which affected only sparc.
sparc has 4 byte long, but needs 8 byte alignment. recently the DIR
struct was changed to contain some off_t, which needs 8 byte alignment.
turns out the allocator calculated the bias for alignment, and then
subtracted out it's private linkage storage afterwards. on hppa this
worked because a 8-byte object can be loaded at a 4-byte boundary; on
all other architectures the situation was either 4/4 or 8/8.
thanks for a bit of help from drahn
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ld.so/util.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/libexec/ld.so/util.c b/libexec/ld.so/util.c index 00982811297..0be5e29d919 100644 --- a/libexec/ld.so/util.c +++ b/libexec/ld.so/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.20 2008/10/02 20:12:08 kurt Exp $ */ +/* $OpenBSD: util.c,v 1.21 2010/10/30 15:36:32 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -80,7 +80,7 @@ _dl_malloc(size_t need) { long *p, *t, *n, have; - need = (need + 8 + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1); + need = (need + 2*DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1); if ((t = _dl_malloc_free) != 0) { /* Try free list first */ n = (long *)&_dl_malloc_free; @@ -90,7 +90,7 @@ _dl_malloc(size_t need) } if (t) { *n = *t; - _dl_memset(t, 0, t[-1] - sizeof(long)); + _dl_memset(t, 0, t[-1] - DL_MALLOC_ALIGN); return((void *)t); } } @@ -98,8 +98,9 @@ _dl_malloc(size_t need) if (need > have) { if (have >= 8 + DL_MALLOC_ALIGN) { p = _dl_malloc_pool; - *p = have; - _dl_free((void *)(p + 1)); /* move to freelist */ + p = (void *) ((long)p + DL_MALLOC_ALIGN); + p[-1] = have; + _dl_free((void *)p); /* move to freelist */ } _dl_malloc_pool = (void *)_dl_mmap((void *)0, _dl_round_page(need), PROT_READ|PROT_WRITE, @@ -112,8 +113,9 @@ _dl_malloc(size_t need) p = _dl_malloc_pool; _dl_malloc_pool += need; _dl_memset(p, 0, need); - *p = need; - return((void *)(p + 1)); + p = (void *) ((long)p + DL_MALLOC_ALIGN); + p[-1] = need; + return (p); } void |