summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorvangyzen <vangyzen@FreeBSD.org>2016-11-30 20:48:44 +0000
committervangyzen <vangyzen@FreeBSD.org>2016-11-30 20:48:44 +0000
commitb9831816e51fba390d17deb4b4b6075a2350f42c (patch)
tree7c6e0b6a2e675962a8a192d039e487c0db63e780 /lib
parentd3b47ab79c9ce879e5f157cb71dbf91f035f3925 (diff)
downloadFreeBSD-src-b9831816e51fba390d17deb4b4b6075a2350f42c.zip
FreeBSD-src-b9831816e51fba390d17deb4b4b6075a2350f42c.tar.gz
MFC r308904
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) Sponsored by: Dell EMC
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/locale/wcstod.c13
-rw-r--r--lib/libc/locale/wcstof.c20
-rw-r--r--lib/libc/locale/wcstold.c13
3 files changed, 31 insertions, 15 deletions
diff --git a/lib/libc/locale/wcstod.c b/lib/libc/locale/wcstod.c
index 8bc46a7..c6ae141 100644
--- a/lib/libc/locale/wcstod.c
+++ b/lib/libc/locale/wcstod.c
@@ -54,11 +54,13 @@ wcstod_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
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, wchar_t ** __restrict endptr,
*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, wchar_t ** __restrict endptr,
* 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);
diff --git a/lib/libc/locale/wcstof.c b/lib/libc/locale/wcstof.c
index 93a5af8..99ce0fe 100644
--- a/lib/libc/locale/wcstof.c
+++ b/lib/libc/locale/wcstof.c
@@ -50,27 +50,37 @@ wcstof_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
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);
diff --git a/lib/libc/locale/wcstold.c b/lib/libc/locale/wcstold.c
index fcfd48f..89c92d9 100644
--- a/lib/libc/locale/wcstold.c
+++ b/lib/libc/locale/wcstold.c
@@ -48,32 +48,35 @@ wcstold_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
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;
OpenPOWER on IntegriCloud