From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2823 invoked by alias); 29 Nov 2004 12:00:20 -0000 Mailing-List: contact libc-hacker-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sources.redhat.com Received: (qmail 2804 invoked from network); 29 Nov 2004 12:00:19 -0000 Received: from unknown (HELO mysicka.ms.mff.cuni.cz) (195.113.15.26) by sourceware.org with SMTP; 29 Nov 2004 12:00:19 -0000 Received: from sunsite.mff.cuni.cz (sunsite.mff.cuni.cz [127.0.0.1]) by mysicka.ms.mff.cuni.cz (8.13.1/8.13.1) with ESMTP id iATC0HrE032020; Mon, 29 Nov 2004 13:00:17 +0100 Received: (from jj@localhost) by sunsite.mff.cuni.cz (8.13.1/8.13.1/Submit) id iATC0H8k032015; Mon, 29 Nov 2004 13:00:17 +0100 Date: Mon, 29 Nov 2004 12:00:00 -0000 From: Jakub Jelinek To: Ulrich Drepper Cc: Glibc hackers Subject: [PATCH] Fix strtold Message-ID: <20041129120017.GH8259@sunsite.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i X-SW-Source: 2004-11/txt/msg00073.txt.bz2 Hi! (echo '#include '; echo 'int main (void) { strtold("42.00000000000000000001", NULL); return 0; }') \ | gcc -O2 -D_GNU_SOURCE -o /tmp/test -m32 -xc -; valgrind --tool=memcheck /tmp/test ==31767== Memcheck, a memory error detector for x86-linux. ==31767== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al. ==31767== Using valgrind-2.2.0, a program supervision framework for x86-linux. ==31767== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al. ==31767== For more details, rerun with: -v ==31767== ==31767== Conditional jump or move depends on uninitialised value(s) ==31767== at 0x3BB68F: __GI_____strtold_l_internal (in /lib/tls/libc-2.3.3.so) ==31767== by 0x3B5117: __GI___strtold_internal (in /lib/tls/libc-2.3.3.so) ==31767== by 0x80483A7: main (in /tmp/test) ==31767== ==31767== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 1) ==31767== malloc/free: in use at exit: 0 bytes in 0 blocks. ==31767== malloc/free: 0 allocs, 0 frees, 0 bytes allocated. ==31767== For a detailed leak analysis, rerun with: --leak-check=yes ==31767== For counts of detected errors, rerun with: -v I don't see anything that would make bits <= 0 and if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG) cases different from the last one regarding whether num needs to be shifted up by (empty + 1) limbs up or not and it is IMHO consistent with what e.g. densize == 2 handling does. In case 2 there are 3 cases: 1) n1 = num[1]; n0 = num[0]; if numsize == densize 1) n1 = 0; n0 = num[0]; if num[0] >= d1 2) n1 = num[0]; n0 = 0; otherwise Now, the check corresponding to num[0] >= d1 is done by if (__mpn_cmp (num, &den[densize - numsize], numsize) > 0) num[numsize++] = 0; in the default case, so we need just the two cases (if densize == numsize, shift up by 1 limb, otherwise shift up by densize - numsize + 1 limbs). Before the if (numsize < densize) test, num is valid from num[0] up to num[numsize - 1]. After this if/else, we use n0 = num[densize]; unconditionally, so num[densize] must be valid (and that's densize - numsize + 1 limbs over what was defined before). The following patch fixes the problem for me and make check passed with it. Do you agree? 2004-11-29 Jakub Jelinek * stdlib/strtod_l.c (INTERNAL (__STRTOF)): If densize > 2 and numsize < densize, always shift num up by empty + 1 limbs. --- libc/stdlib/strtod_l.c.jj 2004-08-04 14:47:56.000000000 +0200 +++ libc/stdlib/strtod_l.c 2004-11-29 11:03:09.584378402 +0100 @@ -1442,15 +1442,10 @@ INTERNAL (__STRTOF) (nptr, endptr, group if (numsize < densize) { mp_size_t empty = densize - numsize; + register int i; if (bits <= 0) - { - register int i; - for (i = numsize; i > 0; --i) - num[i + empty] = num[i - 1]; - MPN_ZERO (num, empty + 1); - exponent -= empty * BITS_PER_MP_LIMB; - } + exponent -= empty * BITS_PER_MP_LIMB; else { if (bits + empty * BITS_PER_MP_LIMB <= MANT_DIG) @@ -1459,7 +1454,6 @@ INTERNAL (__STRTOF) (nptr, endptr, group cannot optimize the `else' case that good and this reflects all currently used FLOAT types and GMP implementations. */ - register int i; #if RETURN_LIMB_SIZE <= 2 assert (empty == 1); __mpn_lshift_1 (retval, RETURN_LIMB_SIZE, @@ -1470,9 +1464,6 @@ INTERNAL (__STRTOF) (nptr, endptr, group while (i >= 0) retval[i--] = 0; #endif - for (i = numsize; i > 0; --i) - num[i + empty] = num[i - 1]; - MPN_ZERO (num, empty + 1); } else { @@ -1492,6 +1483,9 @@ INTERNAL (__STRTOF) (nptr, endptr, group } bits += empty * BITS_PER_MP_LIMB; } + for (i = numsize; i > 0; --i) + num[i + empty] = num[i - 1]; + MPN_ZERO (num, empty + 1); } else { Jakub