summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1998-05-06 12:54:05 +0000
committerUlrich Drepper <drepper@redhat.com>1998-05-06 12:54:05 +0000
commitb22fc5f5651706304ac09305ac3ee5bf84516378 (patch)
tree3c7b8ccb876ea0e4d75c511ce9abafbd7735ac38
parent67c2095b5423e09351be1257701a87991aaccde6 (diff)
downloadglibc-b22fc5f5651706304ac09305ac3ee5bf84516378.tar.gz
glibc-b22fc5f5651706304ac09305ac3ee5bf84516378.tar.xz
glibc-b22fc5f5651706304ac09305ac3ee5bf84516378.zip
Update.
1998-05-06 12:51  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/i386/fpu/bits/mathinline.h (pow): Use long long int for
	test for integer.

	* sysdeps/libm-i387/e_pow.S: Correctly shift double word.
	* sysdeps/libm-i387/e_powl.S: Likewise.

1998-03-31  Wolfram Gloger  <wmglo@dent.med.uni-muenchen.de>

	* malloc/malloc.c (chunk2mem_check, top_check): New functions.
	(malloc_check, free_check, realloc_check, memalign_check): Use
	them to improve overrun checking.  Overruns of a single byte and
	corruption of the top chunk are now detected much more reliably.

1998-05-06  Andreas Jaeger  <aj@arthur.rhein-neckar.de>

	* math/libm-test.c (pow_test): Add test for special value from PR
	libc/590.
-rw-r--r--ChangeLog20
-rw-r--r--Makeconfig32
-rw-r--r--Makefile33
-rw-r--r--Makerules63
-rw-r--r--malloc/malloc.c163
-rw-r--r--manual/Makefile5
-rw-r--r--math/libm-test.c5
-rw-r--r--sysdeps/i386/fpu/bits/mathinline.h2
-rw-r--r--sysdeps/libm-i387/e_pow.S3
-rw-r--r--sysdeps/libm-i387/e_powl.S3
10 files changed, 204 insertions, 125 deletions
diff --git a/ChangeLog b/ChangeLog
index 79aa0cddec..cdc8c2e0e8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+1998-05-06 12:51  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/i386/fpu/bits/mathinline.h (pow): Use long long int for
+	test for integer.
+
+	* sysdeps/libm-i387/e_pow.S: Correctly shift double word.
+	* sysdeps/libm-i387/e_powl.S: Likewise.
+
+1998-03-31  Wolfram Gloger  <wmglo@dent.med.uni-muenchen.de>
+
+	* malloc/malloc.c (chunk2mem_check, top_check): New functions.
+	(malloc_check, free_check, realloc_check, memalign_check): Use
+	them to improve overrun checking.  Overruns of a single byte and
+	corruption of the top chunk are now detected much more reliably.
+
+1998-05-06  Andreas Jaeger  <aj@arthur.rhein-neckar.de>
+
+	* math/libm-test.c (pow_test): Add test for special value from PR
+	libc/590.
+
 1998-05-06  Ulrich Drepper  <drepper@cygnus.com>
 
 	* sysdeps/unix/sysv/linux/bits/errno.h: Undefine EILSEQ before
diff --git a/Makeconfig b/Makeconfig
index 39cb3cda0e..1a93b0aefd 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -754,4 +754,36 @@ have-thread-library = yes
 rpath-link := $(rpath-link):$(common-objpfx)linuxthreads
 endif
 
+ifndef avoid-generated
+-include $(common-objpfx)sysd-dirs
+define \n
+
+
+endef
+sysdep-subdirs := $(subst $(\n), ,$(sysdep-subdirs))
+endif
+
+# These are the subdirectories containing the library source.
+subdirs = csu assert ctype db2 locale intl catgets math setjmp signal stdlib \
+	  stdio-common $(stdio) malloc string wcsmbs time dirent grp pwd \
+	  posix io termios resource misc socket sysvipc gmon gnulib iconv \
+	  iconvdata wctype manual shadow md5-crypt po argp $(add-ons) nss \
+	  localedata timezone rt $(sysdep-subdirs) $(binfmt-subdir)
+
+# The mach and hurd subdirectories have many generated header files which
+# much of the rest of the library depends on, so it is best to build them
+# first (and mach before hurd, at that).  The before-compile additions in
+# sysdeps/{mach,hurd}/Makefile should make it reliably work for these files
+# not to exist when making in other directories, but it will be slower that
+# way with more somewhat expensive `make' invocations.
+subdirs	:= $(filter mach,$(subdirs)) $(filter hurd,$(subdirs)) \
+	   $(filter-out mach hurd,$(subdirs))
+
+all-Subdirs-files = $(wildcard $(addsuffix /Subdirs, $(config-sysdirs)))
+$(common-objpfx)sysd-dirs: $(common-objpfx)config.make $(all-Subdirs-files)
+	(echo define sysdep-subdirs;				\
+	 sed 's/#.*$$//' $(all-Subdirs-files) /dev/null;	\
+	 echo endef) > $@-tmp
+	mv -f $@-tmp $@
+
 endif # Makeconfig not yet included
diff --git a/Makefile b/Makefile
index 63d361093f..bbece0bd08 100644
--- a/Makefile
+++ b/Makefile
@@ -50,32 +50,6 @@ endif
 configure: configure.in aclocal.m4; $(autoconf-it)
 %/configure: %/configure.in aclocal.m4; $(autoconf-it)
 
-ifndef avoid-generated
--include $(objpfx)sysd-dirs
-define \n
-
-
-endef
-sysdep-subdirs := $(subst $(\n), ,$(sysdep-subdirs))
-endif
-
-# These are the subdirectories containing the library source.
-subdirs = csu assert ctype db2 locale intl catgets math setjmp signal stdlib \
-	  stdio-common $(stdio) malloc string wcsmbs time dirent grp pwd \
-	  posix io termios resource misc socket sysvipc gmon gnulib iconv \
-	  iconvdata wctype manual shadow md5-crypt po argp $(add-ons) nss \
-	  localedata timezone rt $(sysdep-subdirs) $(binfmt-subdir)
-export subdirs := $(subdirs)	# Benign, useless in GNU make before 3.63.
-
-# The mach and hurd subdirectories have many generated header files which
-# much of the rest of the library depends on, so it is best to build them
-# first (and mach before hurd, at that).  The before-compile additions in
-# sysdeps/{mach,hurd}/Makefile should make it reliably work for these files
-# not to exist when making in other directories, but it will be slower that
-# way with more somewhat expensive `make' invocations.
-subdirs	:= $(filter mach,$(subdirs)) $(filter hurd,$(subdirs)) \
-	   $(filter-out mach hurd,$(subdirs))
-
 # All initialization source files.
 +subdir_inits	:= $(wildcard $(foreach dir,$(subdirs),$(dir)/init-$(dir).c))
 # All subdirectories containing initialization source files.
@@ -158,13 +132,6 @@ ifeq (yes,$(build-shared))
 # Build the shared object from the PIC object library.
 lib: $(common-objpfx)libc.so
 endif
-
-all-Subdirs-files = $(wildcard $(addsuffix /Subdirs, $(config-sysdirs)))
-$(objpfx)sysd-dirs: $(+sysdir_pfx)config.make $(all-Subdirs-files)
-	(echo define sysdep-subdirs;				\
-	 sed 's/#.*$$//' $(all-Subdirs-files) /dev/null;	\
-	 echo endef) > $@-tmp
-	mv -f $@-tmp $@
 
 all-Banner-files = $(wildcard $(addsuffix /Banner, $(subdirs)))
 $(objpfx)version-info.h: $(+sysdir_pfx)config.make $(all-Banner-files)
diff --git a/Makerules b/Makerules
index 76cbe6b1be..ff89ffe817 100644
--- a/Makerules
+++ b/Makerules
@@ -369,22 +369,16 @@ ifndef libc.so-version
 static-only-routines =
 endif
 
-elide-routines.oS = $(filter-out $(static-only-routines),\
-				 $(routines) $(aux) $(sysdep_routines))
-
-ifdef static-only-routines
+elide-routines.oS += $(filter-out $(static-only-routines),\
+				  $(routines) $(aux) $(sysdep_routines))
 elide-routines.os += $(static-only-routines)
-endif
 
-ifdef shared-only-routines
 # If we have versioned code we don't need the old versions in any of the
 # static libraries.
-define o-iterator-doit
-elide-routines.$o := $(shared-only-routines)
-endef
-object-suffixes-left := $(filter-out .os,$(object-suffixes))
-include $(o-iterator)
-endif
+elide-routines.o  += $(shared-only-routines)
+elide-routines.op += $(shared-only-routines)
+elide-routines.og += $(shared-only-routines)
+elide-routines.ob += $(shared-only-routines)
 
 # Don't try to use -lc when making libc.so itself.
 # Also omits crti.o and crtn.o, which we do not want
@@ -497,14 +491,14 @@ CREATE_ARFLAGS := cru$(verbose)
 # This makes all the object files in the parent library archive.
 
 .PHONY: lib lib-noranlib
-lib: lib-noranlib $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))
+lib: $(foreach l,$(libtypes),$(patsubst %,$(common-objpfx)$l,c))
+lib-noranlib: libobjs
 
 # For object-suffix $o, the list of objects with that suffix.
 # Makefiles can define `elide-routines.so = foo' to leave foo.so out.
 o-objects = $(patsubst %.o,%$o,$(filter-out $(patsubst %,$(objpfx)%.o,\
 						       $(elide-routines$o)),\
 					    $(objects)))
-lib-noranlib: libobjs
 others: $(addprefix $(objpfx),$(install-lib))
 
 ifndef objects
@@ -525,52 +519,33 @@ define o-iterator-doit
 $(objpfx)stamp$o: $(o-objects); $$(do-stamp)
 endef
 define do-stamp
-	echo '$(patsubst $(common-objpfx)%,%,$^)' > $@T
-	mv -f $@T $@
+echo '$(patsubst $(common-objpfx)%,%,$^)' > $@T
+mv -f $@T $@
 endef
-ifdef static-only-routines
 object-suffixes-left := $(object-suffixes-for-libc)
-else
-object-suffixes-left := $(object-suffixes)
-endif
 include $(o-iterator)
 
-ifndef static-only-routines
-subdir_lib: $(objpfx)stamp.oS
-$(objpfx)stamp.oS:
-	$(make-target-directory)
-	rm -f $@; > $@
-endif
-
 endif
 
 # Now define explicit rules to build the library archives; these depend
 # on the stamp files built above.  The rule always destroys and recreates
-# the library from scratch; it's faster (!) that way.
+# the library from scratch; it's faster that way.
 define o-iterator-doit
 $(common-objpfx)$(patsubst %,$(libtype$o),c): \
 		$(subdirs-stamp-o) $(common-objpfx)stamp$o; $$(do-makelib)
 endef
 define do-makelib
-	(set -e; cd $(common-objdir); 			  \
-	$(AR) $(CREATE_ARFLAGS) $(@F)T			  \
-		`cat $(patsubst $(common-objpfx)%,%,$^)`; \
-	$(RANLIB) $(@F)T;				  \
-	mv -f $(@F)T $(@F))
+cd $(common-objdir) && \
+$(AR) $(CREATE_ARFLAGS) $(@F)T `cat $(patsubst $(common-objpfx)%,%,$^)`
+$(RANLIB) $@T
+mv -f $@T $@
 endef
-ifndef subdir
-subdirs-stamps := $(foreach d,$(subdirs),$(common-objpfx)$d/stamp%)
-subdirs-stamp-o = $(subst %,$o,$(subdirs-stamps))
-$(subdirs-stamps): subdir_lib;
-endif
-# The elf directory needs to know subdirs-stamp-o; otherwise libc_pic.a
-# is mangled. FIXME: It would be cleaner to move the final construction
-# of ld.so to top level.
-ifeq ($(subdir),elf)
 subdirs-stamps := $(foreach d,$(subdirs),$(common-objpfx)$d/stamp%)
 subdirs-stamp-o = $(subst %,$o,$(subdirs-stamps))
+ifndef subdir
+$(subdirs-stamps): $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o) \
+		   subdir_lib;
 endif
-
 object-suffixes-left = $(object-suffixes-for-libc)
 include $(o-iterator)
 
@@ -939,8 +914,10 @@ common-clean: common-mostlyclean
 # looking for references to <stub-tag.h>.  Then we grovel over each
 # referenced source file to see what stub function it defines.
 
+ifdef objpfx
 .PHONY: stubs # The parent Makefile calls this target.
 stubs: $(objpfx)stubs
+endif
 s = $(sysdep_dir)/generic
 $(objpfx)stubs: $(+depfiles)
 # Use /dev/null since `...` might expand to empty.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 4a65f520d7..03bc5569b9 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -523,6 +523,14 @@ do {                                                                          \
 #define MAP_ANONYMOUS MAP_ANON
 #endif
 
+#ifndef MAP_NORESERVE
+# ifdef MAP_AUTORESRV
+#  define MAP_NORESERVE MAP_AUTORESRV
+# else
+#  define MAP_NORESERVE 0
+# endif
+#endif
+
 #endif /* HAVE_MMAP */
 
 /*
@@ -1757,15 +1765,15 @@ __malloc_check_init()
 
 static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */
 
-#define MMAP(size, prot) ((dev_zero_fd < 0) ? \
+#define MMAP(size, prot, flags) ((dev_zero_fd < 0) ? \
  (dev_zero_fd = open("/dev/zero", O_RDWR), \
-  mmap(0, (size), (prot), MAP_PRIVATE, dev_zero_fd, 0)) : \
-   mmap(0, (size), (prot), MAP_PRIVATE, dev_zero_fd, 0))
+  mmap(0, (size), (prot), (flags), dev_zero_fd, 0)) : \
+   mmap(0, (size), (prot), (flags), dev_zero_fd, 0))
 
 #else
 
-#define MMAP(size, prot) \
- (mmap(0, (size), (prot), MAP_PRIVATE|MAP_ANONYMOUS, -1, 0))
+#define MMAP(size, prot, flags) \
+ (mmap(0, (size), (prot), (flags)|MAP_ANONYMOUS, -1, 0))
 
 #endif
 
@@ -1791,7 +1799,7 @@ mmap_chunk(size) size_t size;
    */
   size = (size + SIZE_SZ + page_mask) & ~page_mask;
 
-  p = (mchunkptr)MMAP(size, PROT_READ|PROT_WRITE);
+  p = (mchunkptr)MMAP(size, PROT_READ|PROT_WRITE, MAP_PRIVATE);
   if(p == (mchunkptr) MAP_FAILED) return 0;
 
   n_mmaps++;
@@ -1920,7 +1928,11 @@ new_heap(size) size_t size;
     size = HEAP_MAX_SIZE;
   size = (size + page_mask) & ~page_mask;
 
-  p1 = (char *)MMAP(HEAP_MAX_SIZE<<1, PROT_NONE);
+  /* A memory region aligned to a multiple of HEAP_MAX_SIZE is needed.
+     No swap space needs to be reserved for the following large
+     mapping (on Linux, this is the case for all non-writable mappings
+     anyway). */
+  p1 = (char *)MMAP(HEAP_MAX_SIZE<<1, PROT_NONE, MAP_PRIVATE|MAP_NORESERVE);
   if(p1 == MAP_FAILED)
     return 0;
   p2 = (char *)(((unsigned long)p1 + HEAP_MAX_SIZE) & ~(HEAP_MAX_SIZE-1));
@@ -2014,6 +2026,7 @@ arena_get2(a_tsd, size) arena *a_tsd; size_t size;
   }
 
   /* Check the global, circularly linked list for available arenas. */
+ repeat:
   do {
     if(!mutex_trylock(&a->mutex)) {
       THREAD_STAT(++(a->stat_lock_loop));
@@ -2023,6 +2036,16 @@ arena_get2(a_tsd, size) arena *a_tsd; size_t size;
     a = a->next;
   } while(a != a_tsd);
 
+  /* If not even the list_lock can be obtained, try again.  This can
+     happen during `atfork', or for example on systems where thread
+     creation makes it temporarily impossible to obtain _any_
+     locks. */
+  if(mutex_trylock(&list_lock)) {
+    a = a_tsd;
+    goto repeat;
+  }
+  (void)mutex_unlock(&list_lock);
+
   /* Nothing immediately available, so generate a new arena. */
   h = new_heap(size + (sizeof(*h) + sizeof(*a) + MALLOC_ALIGNMENT));
   if(!h)
@@ -3780,9 +3803,6 @@ malloc_update_mallinfo(ar_ptr, mi) arena *ar_ptr; struct mallinfo *mi;
 #endif
   INTERNAL_SIZE_T avail;
 
-  /* Initialize the memory.  */
-  memset (mi, '\0', sizeof (struct mallinfo));
-
   (void)mutex_lock(&ar_ptr->mutex);
   avail = chunksize(top(ar_ptr));
   navail = ((long)(avail) >= (long)MINSIZE)? 1 : 0;
@@ -3806,6 +3826,7 @@ malloc_update_mallinfo(ar_ptr, mi) arena *ar_ptr; struct mallinfo *mi;
 
   mi->arena = ar_ptr->size;
   mi->ordblks = navail;
+  mi->smblks = mi->usmblks = mi->fsmblks = 0; /* clear unused fields */
   mi->uordblks = ar_ptr->size - avail;
   mi->fordblks = avail;
   mi->hblks = n_mmaps;
@@ -4136,13 +4157,39 @@ mALLOC_SET_STATe(msptr) Void_t* msptr;
 
 /* A simple, standard set of debugging hooks.  Overhead is `only' one
    byte per chunk; still this will catch most cases of double frees or
-   overruns. */
+   overruns.  The goal here is to avoid obscure crashes due to invalid
+   usage, unlike in the MALLOC_DEBUG code. */
 
 #define MAGICBYTE(p) ( ( ((size_t)p >> 3) ^ ((size_t)p >> 11)) & 0xFF )
 
+/* Instrument a chunk with overrun detector byte(s) and convert it
+   into a user pointer with requested size sz. */
+
+static Void_t*
+#if __STD_C
+chunk2mem_check(mchunkptr p, size_t sz)
+#else
+chunk2mem_check(p, sz) mchunkptr p; size_t sz;
+#endif
+{
+  unsigned char* m_ptr = (unsigned char*)chunk2mem(p);
+  size_t i;
+
+  for(i = chunksize(p) - (chunk_is_mmapped(p) ? 2*SIZE_SZ+1 : SIZE_SZ+1);
+      i > sz;
+      i -= 0xFF) {
+    if(i-sz < 0x100) {
+      m_ptr[i] = (unsigned char)(i-sz);
+      break;
+    }
+    m_ptr[i] = 0xFF;
+  }
+  m_ptr[sz] = MAGICBYTE(p);
+  return (Void_t*)m_ptr;
+}
+
 /* Convert a pointer to be free()d or realloc()ed to a valid chunk
-   pointer.  If the provided pointer is not valid, return NULL.  The
-   goal here is to avoid crashes, unlike in the MALLOC_DEBUG code. */
+   pointer.  If the provided pointer is not valid, return NULL. */
 
 static mchunkptr
 internal_function
@@ -4153,7 +4200,8 @@ mem2chunk_check(mem) Void_t* mem;
 #endif
 {
   mchunkptr p;
-  INTERNAL_SIZE_T sz;
+  INTERNAL_SIZE_T sz, c;
+  unsigned char magic;
 
   p = mem2chunk(mem);
   if(!aligned_OK(p)) return NULL;
@@ -4166,9 +4214,11 @@ mem2chunk_check(mem) Void_t* mem;
                             (long)prev_chunk(p)<(long)sbrk_base ||
                             next_chunk(prev_chunk(p))!=p) ))
       return NULL;
-    if(*((unsigned char*)p + sz + (SIZE_SZ-1)) != MAGICBYTE(p))
-      return NULL;
-    *((unsigned char*)p + sz + (SIZE_SZ-1)) ^= 0xFF;
+    magic = MAGICBYTE(p);
+    for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
+      if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
+    }
+    ((unsigned char*)p)[sz] ^= 0xFF;
   } else {
     unsigned long offset, page_mask = malloc_getpagesize-1;
 
@@ -4184,13 +4234,53 @@ mem2chunk_check(mem) Void_t* mem;
        ( (((unsigned long)p - p->prev_size) & page_mask) != 0 ) ||
        ( (sz = chunksize(p)), ((p->prev_size + sz) & page_mask) != 0 ) )
       return NULL;
-    if(*((unsigned char*)p + sz - 1) != MAGICBYTE(p))
-      return NULL;
-    *((unsigned char*)p + sz - 1) ^= 0xFF;
+    magic = MAGICBYTE(p);
+    for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
+      if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
+    }
+    ((unsigned char*)p)[sz] ^= 0xFF;
   }
   return p;
 }
 
+/* Check for corruption of the top chunk, and try to recover if
+   necessary. */
+
+static int
+top_check()
+{
+  mchunkptr t = top(&main_arena);
+  char* brk, * new_brk;
+  INTERNAL_SIZE_T front_misalign, sbrk_size;
+  unsigned long pagesz = malloc_getpagesize;
+
+  if((char*)t + chunksize(t) == sbrk_base + sbrked_mem ||
+     t == initial_top(&main_arena)) return 0;
+
+  switch(check_action) {
+  case 1:
+    fprintf(stderr, "malloc: top chunk is corrupt\n");
+    break;
+  case 2:
+    abort();
+  }
+  /* Try to set up a new top chunk. */
+  brk = MORECORE(0);
+  front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;
+  if (front_misalign > 0)
+    front_misalign = MALLOC_ALIGNMENT - front_misalign;
+  sbrk_size = front_misalign + top_pad + MINSIZE;
+  sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1));
+  new_brk = (char*)(MORECORE (sbrk_size));
+  if (new_brk == (char*)(MORECORE_FAILURE)) return -1;
+  sbrked_mem = (new_brk - sbrk_base) + sbrk_size;
+
+  top(&main_arena) = (mchunkptr)(brk + front_misalign);
+  set_head(top(&main_arena), (sbrk_size - front_misalign) | PREV_INUSE);
+
+  return 0;
+}
+
 static Void_t*
 #if __STD_C
 malloc_check(size_t sz, const Void_t *caller)
@@ -4202,16 +4292,10 @@ malloc_check(sz, caller) size_t sz; const Void_t *caller;
   INTERNAL_SIZE_T nb = request2size(sz + 1);
 
   (void)mutex_lock(&main_arena.mutex);
-  victim = chunk_alloc(&main_arena, nb);
+  victim = (top_check() >= 0) ? chunk_alloc(&main_arena, nb) : NULL;
   (void)mutex_unlock(&main_arena.mutex);
   if(!victim) return NULL;
-  nb = chunksize(victim);
-  if(chunk_is_mmapped(victim))
-    --nb;
-  else
-    nb += SIZE_SZ - 1;
-  *((unsigned char*)victim + nb) = MAGICBYTE(victim);
-  return chunk2mem(victim);
+  return chunk2mem_check(victim, sz);
 }
 
 static void
@@ -4290,7 +4374,7 @@ realloc_check(oldmem, bytes, caller)
       if(oldsize - SIZE_SZ >= nb) newp = oldp; /* do nothing */
       else {
         /* Must alloc, copy, free. */
-        newp = chunk_alloc(&main_arena, nb);
+        newp = (top_check() >= 0) ? chunk_alloc(&main_arena, nb) : NULL;
         if (newp) {
           MALLOC_COPY(chunk2mem(newp), oldmem, oldsize - 2*SIZE_SZ);
           munmap_chunk(oldp);
@@ -4301,7 +4385,8 @@ realloc_check(oldmem, bytes, caller)
 #endif
   } else {
 #endif /* HAVE_MMAP */
-    newp = chunk_realloc(&main_arena, oldp, oldsize, nb);
+    newp = (top_check() >= 0) ?
+      chunk_realloc(&main_arena, oldp, oldsize, nb) : NULL;
 #if 0 /* Erase freed memory. */
     nb = chunksize(newp);
     if(oldp<newp || oldp>=chunk_at_offset(newp, nb)) {
@@ -4317,13 +4402,7 @@ realloc_check(oldmem, bytes, caller)
   (void)mutex_unlock(&main_arena.mutex);
 
   if(!newp) return NULL;
-  nb = chunksize(newp);
-  if(chunk_is_mmapped(newp))
-    --nb;
-  else
-    nb += SIZE_SZ - 1;
-  *((unsigned char*)newp + nb) = MAGICBYTE(newp);
-  return chunk2mem(newp);
+  return chunk2mem_check(newp, bytes);
 }
 
 static Void_t*
@@ -4342,16 +4421,10 @@ memalign_check(alignment, bytes, caller)
 
   nb = request2size(bytes+1);
   (void)mutex_lock(&main_arena.mutex);
-  p = chunk_align(&main_arena, nb, alignment);
+  p = (top_check() >= 0) ? chunk_align(&main_arena, nb, alignment) : NULL;
   (void)mutex_unlock(&main_arena.mutex);
   if(!p) return NULL;
-  nb = chunksize(p);
-  if(chunk_is_mmapped(p))
-    --nb;
-  else
-    nb += SIZE_SZ - 1;
-  *((unsigned char*)p + nb) = MAGICBYTE(p);
-  return chunk2mem(p);
+  return chunk2mem_check(p, bytes);
 }
 
 /* The following hooks are used when the global initialization in
diff --git a/manual/Makefile b/manual/Makefile
index bffbec6ada..d00a3cb586 100644
--- a/manual/Makefile
+++ b/manual/Makefile
@@ -198,7 +198,7 @@ subdir_%: ;
 # None of these should be `subdir_TARGET'; those targets are transformed
 # by the implicit rule above into `TARGET' deps.
 glibc-targets	:= lib objects objs others tests lint.out \
-		   echo-headers echo-distinfo stubs
+		   echo-headers echo-distinfo
 .PHONY: $(glibc-targets)
 $(glibc-targets):
 
@@ -206,7 +206,10 @@ $(glibc-targets):
 # updating the library archives are happy with us, and never think we have
 # changed the library.
 lib: $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o)
+ifdef objpfx
+.PHONY: stubs
 stubs: $(objpfx)stubs
+endif
 $(objpfx)stubs ../po/manual.pot $(objpfx)stamp%:
 	$(make-target-directory)
 	cp /dev/null $@
diff --git a/math/libm-test.c b/math/libm-test.c
index 976e5e8cf1..8ec4f1be4d 100644
--- a/math/libm-test.c
+++ b/math/libm-test.c
@@ -2203,6 +2203,11 @@ pow_test (void)
 
   check_eps ("pow (0.7, 1.2) == 0.65180...", FUNC(pow) (0.7, 1.2),
 	     0.65180494056638638188L, CHOOSE(4e-17L, 0, 0));
+
+#ifdef TEST_DOUBLE
+  check ("pow (-7.49321e+133, -9.80818e+16) == 0",
+	 FUNC(pow) (-7.49321e+133, -9.80818e+16), 0);
+#endif
 }
 
 
diff --git a/sysdeps/i386/fpu/bits/mathinline.h b/sysdeps/i386/fpu/bits/mathinline.h
index 77b6cd5e51..e78c76986b 100644
--- a/sysdeps/i386/fpu/bits/mathinline.h
+++ b/sysdeps/i386/fpu/bits/mathinline.h
@@ -376,7 +376,7 @@ __inline_mathcode2 (fmod, __x, __y, \
 __inline_mathcode2 (pow, __x, __y, \
   register long double __value;						      \
   register long double __exponent;					      \
-  long int __p = (long int) __y;					      \
+  long long int __p = (long long int) __y;				      \
   if (__x == 0.0 && __y > 0.0)						      \
     return 0.0;								      \
   if (__y == (double) __p)						      \
diff --git a/sysdeps/libm-i387/e_pow.S b/sysdeps/libm-i387/e_pow.S
index 45c41b48ab..75ad211872 100644
--- a/sysdeps/libm-i387/e_pow.S
+++ b/sysdeps/libm-i387/e_pow.S
@@ -1,5 +1,5 @@
 /* ix87 specific implementation of pow function.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -125,6 +125,7 @@ ENTRY(__ieee754_pow)
 	fmul	%st(1)		// x : ST*x
 	fxch
 5:	fmul	%st(0), %st	// x*x : ST*x
+	shrl	$1, %edx
 	movl	%eax, %ecx
 	orl	%edx, %ecx
 	jnz	6b
diff --git a/sysdeps/libm-i387/e_powl.S b/sysdeps/libm-i387/e_powl.S
index 0ea4829822..2e09dcc820 100644
--- a/sysdeps/libm-i387/e_powl.S
+++ b/sysdeps/libm-i387/e_powl.S
@@ -1,5 +1,5 @@
 /* ix87 specific implementation of pow function.
-   Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -125,6 +125,7 @@ ENTRY(__ieee754_powl)
 	fmul	%st(1)		// x : ST*x
 	fxch
 5:	fmul	%st(0), %st	// x*x : ST*x
+	shrl	$1, %edx
 	movl	%eax, %ecx
 	orl	%edx, %ecx
 	jnz	6b