Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Nov 2016 20:13:22 +0000 (UTC)
From:      Eric van Gyzen <vangyzen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r308904 - head/lib/libc/locale
Message-ID:  <201611202013.uAKKDM8o047823@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: vangyzen
Date: Sun Nov 20 20:13:22 2016
New Revision: 308904
URL: https://svnweb.freebsd.org/changeset/base/308904

Log:
  Fix error reporting from wcstof()
  
  When wcstof() skipped initial space and then parsing failed, it set
  endptr to the first non-space character.  Fix it to correctly report
  failure by setting endptr to the beginning of the input string.
  The fix is from theraven@, who fixed this bug in wcstod() and
  wcstold() in r227753.
  
  While I'm here:
  
  Move assignments out of declarations in wcstod() and wcstold().
  This is against my personal preference, but it is our agreed style(9).
  
  Set endptr correctly on malloc() failure in all three functions.
  
  Remove an incorrect comment:  This is pointer arithmetic,
  so the code was not actually making that assumption.
  
  wcstold() advanced the wcp pointer beyond leading whitespace
  and then reset it back to the beginning of the string.
  Do not reset it.  This seems to have no functional effect,
  since strtold_l() also skips leading whitespace.  I'm making
  the change to keep this function consistent with wcstof() and
  wcstod(), and because the C11 spec prescribes the use of iswspace()
  to skip leading space.
  
  Reported by:	libc++ unit test for std::stof(std::wstring)
  MFC after:	8 days
  Sponsored by:	Dell EMC

Modified:
  head/lib/libc/locale/wcstod.c
  head/lib/libc/locale/wcstof.c
  head/lib/libc/locale/wcstold.c

Modified: head/lib/libc/locale/wcstod.c
==============================================================================
--- head/lib/libc/locale/wcstod.c	Sun Nov 20 19:39:55 2016	(r308903)
+++ head/lib/libc/locale/wcstod.c	Sun Nov 20 20:13:22 2016	(r308904)
@@ -54,11 +54,13 @@ wcstod_l(const wchar_t * __restrict nptr
 	mbstate_t mbs;
 	double val;
 	char *buf, *end;
-	const wchar_t *wcp = nptr;
+	const wchar_t *wcp;
 	size_t len;
-	size_t spaces = 0;
+	size_t spaces;
 	FIX_LOCALE(locale);
 
+	wcp = nptr;
+	spaces = 0;
 	while (iswspace_l(*wcp, locale)) {
 		wcp++;
 		spaces++;
@@ -80,8 +82,11 @@ wcstod_l(const wchar_t * __restrict nptr
 			*endptr = (wchar_t *)nptr;
 		return (0.0);
 	}
-	if ((buf = malloc(len + 1)) == NULL)
+	if ((buf = malloc(len + 1)) == NULL) {
+		if (endptr != NULL)
+			*endptr = (wchar_t *)nptr;
 		return (0.0);
+	}
 	mbs = initial;
 	wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale);
 
@@ -95,13 +100,11 @@ wcstod_l(const wchar_t * __restrict nptr
 	 * corresponding position in the wide char string.
 	 */
 	if (endptr != NULL) {
-		/* XXX Assume each wide char is one byte. */
 		*endptr = (wchar_t *)nptr + (end - buf);
 		if (buf != end)
 			*endptr += spaces;
 	}
 
-
 	free(buf);
 
 	return (val);

Modified: head/lib/libc/locale/wcstof.c
==============================================================================
--- head/lib/libc/locale/wcstof.c	Sun Nov 20 19:39:55 2016	(r308903)
+++ head/lib/libc/locale/wcstof.c	Sun Nov 20 20:13:22 2016	(r308904)
@@ -50,27 +50,37 @@ wcstof_l(const wchar_t * __restrict nptr
 	char *buf, *end;
 	const wchar_t *wcp;
 	size_t len;
+	size_t spaces;
 	FIX_LOCALE(locale);
 
-	while (iswspace_l(*nptr, locale))
-		nptr++;
-
 	wcp = nptr;
+	spaces = 0;
+	while (iswspace_l(*wcp, locale)) {
+		wcp++;
+		spaces++;
+	}
+
 	mbs = initial;
 	if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) {
 		if (endptr != NULL)
 			*endptr = (wchar_t *)nptr;
 		return (0.0);
 	}
-	if ((buf = malloc(len + 1)) == NULL)
+	if ((buf = malloc(len + 1)) == NULL) {
+		if (endptr != NULL)
+			*endptr = (wchar_t *)nptr;
 		return (0.0);
+	}
 	mbs = initial;
 	wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale);
 
 	val = strtof_l(buf, &end, locale);
 
-	if (endptr != NULL)
+	if (endptr != NULL) {
 		*endptr = (wchar_t *)nptr + (end - buf);
+		if (buf != end)
+			*endptr += spaces;
+	}
 
 	free(buf);
 

Modified: head/lib/libc/locale/wcstold.c
==============================================================================
--- head/lib/libc/locale/wcstold.c	Sun Nov 20 19:39:55 2016	(r308903)
+++ head/lib/libc/locale/wcstold.c	Sun Nov 20 20:13:22 2016	(r308904)
@@ -48,32 +48,35 @@ wcstold_l(const wchar_t * __restrict npt
 	mbstate_t mbs;
 	long double val;
 	char *buf, *end;
-	const wchar_t *wcp = nptr;
+	const wchar_t *wcp;
 	size_t len;
-	size_t spaces = 0;
+	size_t spaces;
 	FIX_LOCALE(locale);
 
+	wcp = nptr;
+	spaces = 0;
 	while (iswspace_l(*wcp, locale)) {
 		wcp++;
 		spaces++;
 	}
 
-	wcp = nptr;
 	mbs = initial;
 	if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) {
 		if (endptr != NULL)
 			*endptr = (wchar_t *)nptr;
 		return (0.0);
 	}
-	if ((buf = malloc(len + 1)) == NULL)
+	if ((buf = malloc(len + 1)) == NULL) {
+		if (endptr != NULL)
+			*endptr = (wchar_t *)nptr;
 		return (0.0);
+	}
 	mbs = initial;
 	wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale);
 
 	val = strtold_l(buf, &end, locale);
 
 	if (endptr != NULL) {
-		/* XXX Assume each wide char is one byte. */
 		*endptr = (wchar_t *)nptr + (end - buf);
 		if (buf != end)
 			*endptr += spaces;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201611202013.uAKKDM8o047823>