Bug 3664 - strtod handling of all-zeros numbers broken
Summary: strtod handling of all-zeros numbers broken
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.4
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-12-06 01:54 UTC by Joseph Myers
Modified: 2014-07-17 14:56 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joseph Myers 2006-12-06 01:54:15 UTC
strtod_l.c contains a conditional which is never going to pass because it
requires both base == 16 and base != 16.

  if ((c < L_('0') || c > L_('9'))
      && (base == 16 && (c < (CHAR_TYPE) TOLOWER (L_('a'))
                         || c > (CHAR_TYPE) TOLOWER (L_('f'))))
#ifdef USE_WIDE_CHAR
      && c != (wint_t) decimal
#else
      && ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
              if (decimal[cnt] != cp[cnt])
                break;
            decimal[cnt] != '\0'; })
#endif
      && (base == 16 && (cp == start_of_digits
                         || (CHAR_TYPE) TOLOWER (c) != L_('p')))
      && (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e')))

I believe the fix is to change "base == 16 &&" to "base != 16 ||" in both
places, "base != 16 &&" to "base == 16 ||", "c < (CHAR_TYPE) TOLOWER (L_('a'))"
to "(CHAR_TYPE) TOLOWER (c) < L_('a')" and likewise for 'f'.

The following test shows that this causes an actual bug.

#include <stdlib.h>
int
main(void)
{
  const char *s = "0x";
  char *ep;
  double r = strtod(s, &ep);
  if (r != 0)
    abort();
  if (ep != s + 1)
    abort();
  exit(0);
}
Comment 1 Ulrich Drepper 2006-12-10 01:52:36 UTC
Fixed in cvs.
Comment 2 Sourceware Commits 2007-01-12 18:07:35 UTC
Subject: Bug 3664

CVSROOT:	/cvs/glibc
Module name:	libc
Branch: 	glibc-2_5-branch
Changes by:	jakub@sourceware.org	2007-01-12 18:07:19

Modified files:
	.              : ChangeLog 
	stdlib         : Makefile strtod_l.c 
Added files:
	stdlib         : tst-atof1.c tst-atof2.c tst-strtod2.c 
	                 tst-strtod3.c 

Log message:
	* stdlib/Makefile (tst-strtod3-ENV): Define.
	
	* stdlib/strtod_l.c (____STRTOF_INTERNAL): Parse thousand
	separators also if no non-zero digits found.
	* stdlib/Makefile (tests): Add tst-strtod3.
	
	[BZ #3664]
	* stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix test to recognize
	empty parsed strings.
	* stdlib/Makefile (tests): Add tst-strtod2.
	* stdlib/tst-strtod2.c: New file.
	
	[BZ #3673]
	* stdlib/strtod_l.c (____STRTOF_INTERNAL): Fix exp_limit
	computation.
	* stdlib/Makefile (tests): Add tst-atof2.
	* stdlib/tst-atof2.c: New file.
	
	[BZ #3674]
	* stdlib/strtod_l.c (____STRTOF_INTERNAL): Adjust exponent value
	correctly if removing trailing zero of hex-float.
	* stdlib/Makefile (tests): Add tst-atof1.
	* stdlib/tst-atof1.c: New file.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/libc/ChangeLog.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.10362.2.28&r2=1.10362.2.29
http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/tst-atof1.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/tst-atof2.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/tst-strtod2.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=NONE&r2=1.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/tst-strtod3.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=NONE&r2=1.1.4.1
http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/Makefile.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.109.2.2&r2=1.109.2.3
http://sourceware.org/cgi-bin/cvsweb.cgi/libc/stdlib/strtod_l.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.14&r2=1.14.2.1