From b22fc5f5651706304ac09305ac3ee5bf84516378 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Wed, 6 May 1998 12:54:05 +0000 Subject: [PATCH] Update. 1998-05-06 12:51 Ulrich Drepper * 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 * 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 * math/libm-test.c (pow_test): Add test for special value from PR libc/590. --- ChangeLog | 20 ++++ Makeconfig | 32 ++++++ Makefile | 33 ------ Makerules | 65 ++++-------- malloc/malloc.c | 163 +++++++++++++++++++++-------- manual/Makefile | 5 +- math/libm-test.c | 5 + sysdeps/i386/fpu/bits/mathinline.h | 2 +- sysdeps/libm-i387/e_pow.S | 3 +- sysdeps/libm-i387/e_powl.S | 3 +- 10 files changed, 205 insertions(+), 126 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 + + * 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 + + * 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 + + * math/libm-test.c (pow_test): Add test for special value from PR + libc/590. + 1998-05-06 Ulrich Drepper * 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 +subdirs-stamps := $(foreach d,$(subdirs),$(common-objpfx)$d/stamp%) +subdirs-stamp-o = $(subst %,$o,$(subdirs-stamps)) ifndef subdir -subdirs-stamps := $(foreach d,$(subdirs),$(common-objpfx)$d/stamp%) -subdirs-stamp-o = $(subst %,$o,$(subdirs-stamps)) -$(subdirs-stamps): subdir_lib; +$(subdirs-stamps): $(foreach o,$(object-suffixes-for-libc),$(objpfx)stamp$o) \ + 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)) -endif - object-suffixes-left = $(object-suffixes-for-libc) include $(o-iterator) @@ -939,8 +914,10 @@ common-clean: common-mostlyclean # looking for references to . 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=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 , 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 , 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