From owner-svn-src-stable@freebsd.org Wed Nov 30 20:48:46 2016 Return-Path: Delivered-To: svn-src-stable@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 6FECDC5EAD4; Wed, 30 Nov 2016 20:48:46 +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 307041F69; Wed, 30 Nov 2016 20:48:46 +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 uAUKmj1v028206; Wed, 30 Nov 2016 20:48:45 GMT (envelope-from vangyzen@FreeBSD.org) Received: (from vangyzen@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uAUKmjBV028203; Wed, 30 Nov 2016 20:48:45 GMT (envelope-from vangyzen@FreeBSD.org) Message-Id: <201611302048.uAUKmjBV028203@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: vangyzen set sender to vangyzen@FreeBSD.org using -f From: Eric van Gyzen Date: Wed, 30 Nov 2016 20:48:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r309334 - stable/10/lib/libc/locale X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Nov 2016 20:48:46 -0000 Author: vangyzen Date: Wed Nov 30 20:48:44 2016 New Revision: 309334 URL: https://svnweb.freebsd.org/changeset/base/309334 Log: 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 Modified: stable/10/lib/libc/locale/wcstod.c stable/10/lib/libc/locale/wcstof.c stable/10/lib/libc/locale/wcstold.c Directory Properties: stable/10/ (props changed) Modified: stable/10/lib/libc/locale/wcstod.c ============================================================================== --- stable/10/lib/libc/locale/wcstod.c Wed Nov 30 20:47:54 2016 (r309333) +++ stable/10/lib/libc/locale/wcstod.c Wed Nov 30 20:48:44 2016 (r309334) @@ -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: stable/10/lib/libc/locale/wcstof.c ============================================================================== --- stable/10/lib/libc/locale/wcstof.c Wed Nov 30 20:47:54 2016 (r309333) +++ stable/10/lib/libc/locale/wcstof.c Wed Nov 30 20:48:44 2016 (r309334) @@ -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: stable/10/lib/libc/locale/wcstold.c ============================================================================== --- stable/10/lib/libc/locale/wcstold.c Wed Nov 30 20:47:54 2016 (r309333) +++ stable/10/lib/libc/locale/wcstold.c Wed Nov 30 20:48:44 2016 (r309334) @@ -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;