From patchwork Thu Dec 15 16:47:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyrill Tkachov X-Patchwork-Id: 88198 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp902431qgi; Thu, 15 Dec 2016 08:47:47 -0800 (PST) X-Received: by 10.84.225.22 with SMTP id t22mr4277497plj.76.1481820467904; Thu, 15 Dec 2016 08:47:47 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id f14si3266918plm.266.2016.12.15.08.47.47 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 Dec 2016 08:47:47 -0800 (PST) Received-SPF: pass (google.com: domain of newlib-return-14223-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org; spf=pass (google.com: domain of newlib-return-14223-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=newlib-return-14223-patch=linaro.org@sourceware.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:date:from:mime-version:to:subject :content-type; q=dns; s=default; b=YlWG7PKun2jJM6IATnGjvAX6elMCB 7qrApxQP2L/2u8oAI6jMjSpkBhAC7B5VHDPreisPTmkyyHaMmAZeG5vDnclxjLPf 3ipCMBdsCyuXS5p+M1oAQl64uQOYr6kyJ0LQHiXyAPgCbGeUWTPLg8fl7iFfgKoH +SdHbGqmbd6IvU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:date:from:mime-version:to:subject :content-type; s=default; bh=P9ZZ8mkoQDkdprzXp01AODXDEYA=; b=HX1 MoXqX1z/EEXLHbewZVjgIcWxSxkgHeW5fw+nfbTdJErjMVRCC4JdRWYq/ri/NK8i 4Xv8qrC0kd99dDS1Z5zNsF8sB7TAFXdJPKM9sKuIwzQNT37Hg2bvRwEZbJUrKQrc MhjuAbmKRDNXZOdHT7+oGN2T4fzv9lgdqZsNKYF8= Received: (qmail 113817 invoked by alias); 15 Dec 2016 16:47:39 -0000 Mailing-List: contact newlib-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: newlib-owner@sourceware.org Delivered-To: mailing list newlib@sourceware.org Received: (qmail 113807 invoked by uid 89); 15 Dec 2016 16:47:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.0 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=aforementioned X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 15 Dec 2016 16:47:28 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 291171516; Thu, 15 Dec 2016 08:47:27 -0800 (PST) Received: from [10.2.207.77] (e100706-lin.cambridge.arm.com [10.2.207.77]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id CC3653F445 for ; Thu, 15 Dec 2016 08:47:26 -0800 (PST) Message-ID: <5852C91D.2020109@foss.arm.com> Date: Thu, 15 Dec 2016 16:47:25 +0000 From: Kyrill Tkachov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: newlib@sourceware.org Subject: [PATCH] Set errno in strtof variants when conversion from double overflows Hi all, I've been investigating some libstdc++ execution failures on newlib bare-metal targets, in particular arm-none-eabi and aarch64-none-elf. In particular: 21_strings/basic_string/numeric_conversions/char/stof.cc 21_strings/basic_string/numeric_conversions/wchar_t/stof.cc These tests perform a conversion from string to a float and end up mapping down to the strtof/wcstof C functions. They create a string from a large number that is representable in double precision but not in single precision and expect strtof to return infinity and set errno to ERANGE so that libstdc++ can throw an exception. But the implementation of strtof uses strtod internally to convert the string to a double and then cast the result to a float. This works for getting the infinity result but doesn't set errno properly. This patch adds a check after the conversion to see if the cast ended up generating an infinity from a non-infinity and sets errno in that case. With this patch the aforementioned tests pass on arm-none-eabi and aarch64-none-elf. Is this ok? If so, can someone please commit it on my behalf? Thanks, Kyrill 2016-12-15 Kyrylo Tkachov * libc/stdlib/strtod.c (strtof_l): Set errno to ERANGE when double to float conversion results in infinity. (strtof): Likewise. * libc/stdlib/wcstod.c (wcstof_l): Likewise. (wcstof): Likewise. diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c index e908fcb..f82f507 100644 --- a/newlib/libc/stdlib/strtod.c +++ b/newlib/libc/stdlib/strtod.c @@ -1293,9 +1293,14 @@ _DEFUN (strtod, (s00, se), float strtof_l (const char *__restrict s00, char **__restrict se, locale_t loc) { - double retval = _strtod_l (_REENT, s00, se, loc); - if (isnan (retval)) + double val = _strtod_l (_REENT, s00, se, loc); + if (isnan (val)) return nanf (NULL); + float retval = (float) val; +#ifndef NO_ERRNO + if (isinf (retval) && !isinf (val)) + _REENT->_errno = ERANGE; +#endif return (float)retval; } @@ -1304,9 +1309,14 @@ _DEFUN (strtof, (s00, se), _CONST char *__restrict s00 _AND char **__restrict se) { - double retval = _strtod_l (_REENT, s00, se, __get_current_locale ()); - if (isnan (retval)) + double val = _strtod_l (_REENT, s00, se, __get_current_locale ()); + if (isnan (val)) return nanf (NULL); + float retval = (float) val; +#ifndef NO_ERRNO + if (isinf (retval) && !isinf (val)) + _REENT->_errno = ERANGE; +#endif return (float)retval; } diff --git a/newlib/libc/stdlib/wcstod.c b/newlib/libc/stdlib/wcstod.c index 43f7b4e..9b7948e 100644 --- a/newlib/libc/stdlib/wcstod.c +++ b/newlib/libc/stdlib/wcstod.c @@ -274,9 +274,14 @@ float wcstof_l (const wchar_t *__restrict nptr, wchar_t **__restrict endptr, locale_t loc) { - double retval = _wcstod_l (_REENT, nptr, endptr, loc); - if (isnan (retval)) + double val = _wcstod_l (_REENT, nptr, endptr, loc); + if (isnan (val)) return nanf (NULL); + float retval = (float) val; +#ifndef NO_ERRNO + if (isinf (retval) && !isinf (val)) + _REENT->_errno = ERANGE; +#endif return (float)retval; } @@ -285,9 +290,15 @@ _DEFUN (wcstof, (nptr, endptr), _CONST wchar_t *__restrict nptr _AND wchar_t **__restrict endptr) { - double retval = _wcstod_l (_REENT, nptr, endptr, __get_current_locale ()); - if (isnan (retval)) + double val = _wcstod_l (_REENT, nptr, endptr, __get_current_locale ()); + if (isnan (val)) return nanf (NULL); + float retval = (float) val; +#ifndef NO_ERRNO + if (isinf (retval) && !isinf (val)) + _REENT->_errno = ERANGE; +#endif + return (float)retval; }