From patchwork Fri Sep 1 10:55:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 137380 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c792:0:b0:3f2:4152:657d with SMTP id b18csp803169vqu; Fri, 1 Sep 2023 03:59:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFZ+BcXvF22U2ZI0ObJj9w1VVBIBw5K89ha2Q9R3br5Sq5D6qFii+QEJXU7w+s8TgBXHwNl X-Received: by 2002:aa7:d5c2:0:b0:523:2e30:aaee with SMTP id d2-20020aa7d5c2000000b005232e30aaeemr1468171eds.32.1693565996431; Fri, 01 Sep 2023 03:59:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693565996; cv=none; d=google.com; s=arc-20160816; b=nvEUPWUcVwT8GxvEpl0qfJLdjuEJ0ejhn04evWW+q/Y/Q5JeteuP2DyqZJ7VZacHzX V2dTOOm1s8nXmHiWsUuaX18KO6JirXHpGH0WHRgxLvMkU7WnRgygUa2NqvQaJx2G+qlN 3GbkpRQl2K9kGfLL+8tTjSGRfkmI3PRZRQF+29tG9AQEaC217mjsLp7w2Xs02Zd5XwMZ 39ygoOOfQRUXjVI5hyjf2Kjg4HJyBjl/OlafqBHdORexoGiRbbwjnVQogMwfT05zkyAu TKJ5xjnfYio9NkhNCIZvsTeSaQ++4/cOvqQnX1fB+me7Z/9Kb6ZNgosrAzaVTyW4GLBk 6fZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=y5yUru6bFgE13KdE1+WSnZjaoKY97CETKwoAdfKusP4=; fh=sJ+2/4g29YdyXkoRrFZSpsL2zxijepB7X/1rB0LDDh8=; b=JOyWRBelzfyn4gpjqrC+vxclHcTca2326Tkd5dEHmM3bMclmYG+RCQi3XuiyHxuE0y Z46NW+7/59ZhmHVmp2Dmy++/6NAssgOXKFv68NNMd5YVWEEQu4VFuwXHQxWkseXIOCpz HFhBFmFyFgDysnXUlkU8wQUBde5SpUb3UdYcHZHXgBIGoc3h4csQdYQfHSv+zuTyMT1l iTv7JFfPH+X6J9On5YxjfZO9FbCuR8dcp44fraitMHGJbmZIRdX6rVt1DpEkCbmbBGJF igqNUumYbyj8+ZV2u4OdQrDkr3G+SdgZqgym9qdC/nrMB3xLxDfFtb+LXWq3dWJ/TxmO ZKGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=agizBv9I; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id l8-20020aa7c308000000b005259e364ce3si2443981edq.290.2023.09.01.03.59.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Sep 2023 03:59:56 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=agizBv9I; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 61E69385B527 for ; Fri, 1 Sep 2023 10:58:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 61E69385B527 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1693565926; bh=y5yUru6bFgE13KdE1+WSnZjaoKY97CETKwoAdfKusP4=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=agizBv9IlnL04v7PWasYM+QgsT0qxF+oKu6bvXlCFw9LQbWii6/Fc0LE2cs+5JSH7 w6Ejc5FzXFC1YirYOtMxRzmRUnEeaLz84LX30PobDymvZQx5CPRwpfe7H/9gBgehkn bo0bNQBDS4w4OkZ8m68fNlgCAyci6m7rbsxKqQ+Q= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id E38F23857347 for ; Fri, 1 Sep 2023 10:55:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E38F23857347 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-613-9X9plWawODKPVPwVkFvsGQ-1; Fri, 01 Sep 2023 06:55:27 -0400 X-MC-Unique: 9X9plWawODKPVPwVkFvsGQ-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4C3AE800193; Fri, 1 Sep 2023 10:55:27 +0000 (UTC) Received: from localhost (unknown [10.42.28.181]) by smtp.corp.redhat.com (Postfix) with ESMTP id 11A2F493110; Fri, 1 Sep 2023 10:55:26 +0000 (UTC) To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix how chrono::parse handles errors for time-of-day values Date: Fri, 1 Sep 2023 11:55:20 +0100 Message-ID: <20230901105526.226787-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLACK autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775832658282280677 X-GMAIL-MSGID: 1775832658282280677 Tested x86_64-linux. Pushed to trunk. -- >8 -- We fail to diagnose an error and extract an incorrect time for cases like "25:59" >> parse("%H:%M", mins). The bad "25" hour value gets ignored (on the basis that we might not care about it if trying to extract something like a weekday or a month name), but then when we get to the end of the function we think we have a valid time from "59" and so the result is 00:59. The problem is that the '__bad_h' value is used for "no hour value read yet" as well as "bad hour value read". If we just set __h = __bad_h and continue, we can't tell later that we read an invalid hour. The fix is to set failbit early when we're trying to extract a time-of-day (e.g. duration or time_point) and we encounter an invalid hour, minute, or second value. We can still delay other error checking to the end. libstdc++-v3/ChangeLog: * include/bits/chrono_io.h (_Parser::operator()): Set failbit early if invalid values are read when _M_need & _TimeOfDay is non-zero. * testsuite/std/time/parse.cc: Check that "25:59" cannot be parsed for "%H:%M". --- libstdc++-v3/include/bits/chrono_io.h | 53 +++++++++++++----------- libstdc++-v3/testsuite/std/time/parse.cc | 7 ++++ 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index f359571b4db..7352df095ff 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -3327,7 +3327,16 @@ namespace __detail __h = __bad_h; } else if (__c == 'H' && __val >= 0 && __val <= 23) - __h = hours(__val); + { + __h = hours(__val); + __h12 = __bad_h; + } + else + { + if (_M_need & _ChronoParts::_TimeOfDay) + __err |= ios_base::failbit; + break; + } } __parts |= _ChronoParts::_TimeOfDay; break; @@ -3392,9 +3401,8 @@ namespace __detail __min = minutes(__val); else { - __h = __bad_h; - __min = __bad_min; - __s = __bad_sec; + if (_M_need & _ChronoParts::_TimeOfDay) + __err |= ios_base::failbit; break; } } @@ -3481,33 +3489,31 @@ namespace __detail else { auto __val = __read_unsigned(2); - if (__val == -1 || __val > 23) + if (__val == -1 || __val > 23) [[unlikely]] { - __h = __bad_h; - __min = __bad_min; - __s = __bad_sec; - break; - } - if (!__read_chr(':')) - { - __err |= ios_base::failbit; + if (_M_need & _ChronoParts::_TimeOfDay) + __err |= ios_base::failbit; break; } + if (!__read_chr(':')) [[unlikely]] + break; __h = hours(__val); __val = __read_unsigned(2); - if (__val == -1 || __val > 60) + if (__val == -1 || __val > 60) [[unlikely]] { - __h = __bad_h; - __min = __bad_min; - __s = __bad_sec; + if (_M_need & _ChronoParts::_TimeOfDay) + __err |= ios_base::failbit; break; } __min = minutes(__val); - __parts |= _ChronoParts::_TimeOfDay; - - if (__c != 'T' || !__read_chr(':')) + if (__c == 'R') + { + __parts |= _ChronoParts::_TimeOfDay; + break; + } + else if (!__read_chr(':')) [[unlikely]] break; } [[fallthrough]]; @@ -3527,13 +3533,12 @@ namespace __detail ratio<1>>) { auto __val = __read_unsigned(__num ? __num : 2); - if (0 <= __val && __val <= 59) + if (0 <= __val && __val <= 59) [[likely]] __s = seconds(__val); else { - __h = __bad_h; - __min = __bad_min; - __s = __bad_sec; + if (_M_need & _ChronoParts::_TimeOfDay) + __err |= ios_base::failbit; break; } } diff --git a/libstdc++-v3/testsuite/std/time/parse.cc b/libstdc++-v3/testsuite/std/time/parse.cc index 46eb7f28c85..86222d59596 100644 --- a/libstdc++-v3/testsuite/std/time/parse.cc +++ b/libstdc++-v3/testsuite/std/time/parse.cc @@ -252,6 +252,13 @@ test_errors() VERIFY( is.eof() && ! is.fail() ); VERIFY( y == 2010y ); + min = -1min; + is.clear(); + is.str("25:59"); + is >> parse("%H:%M", min); // 25h is out of range and needed + VERIFY( is.fail() ); + VERIFY( min == -1min ); + is.clear(); is.str("328 00"); is >> parse("%3C %y", y); // 328 is out of range for %C (PR libstdc++/111162)