From owner-svn-src-head@freebsd.org Sun Nov 20 20:13:24 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 0B7E5C4CCC0; Sun, 20 Nov 2016 20:13:24 +0000 (UTC) (envelope-from vangyzen@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id BC56E16; Sun, 20 Nov 2016 20:13:23 +0000 (UTC) (envelope-from vangyzen@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uAKKDM2C047826; Sun, 20 Nov 2016 20:13:22 GMT (envelope-from vangyzen@FreeBSD.org) Received: (from vangyzen@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uAKKDM8o047823; Sun, 20 Nov 2016 20:13:22 GMT (envelope-from vangyzen@FreeBSD.org) Message-Id: <201611202013.uAKKDM8o047823@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: vangyzen set sender to vangyzen@FreeBSD.org using -f From: Eric van Gyzen Date: Sun, 20 Nov 2016 20:13:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r308904 - head/lib/libc/locale X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Nov 2016 20:13:24 -0000 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;