[libcxx-commits] [libcxx] ab07d06 - [libcxx] Reject month 0 in get_date/__get_month

David Spickett via libcxx-commits libcxx-commits at lists.llvm.org
Fri May 6 03:07:58 PDT 2022


Author: David Spickett
Date: 2022-05-06T10:07:53Z
New Revision: ab07d06e7b864029620927790dfb23b6a5900e13

URL: https://github.com/llvm/llvm-project/commit/ab07d06e7b864029620927790dfb23b6a5900e13
DIFF: https://github.com/llvm/llvm-project/commit/ab07d06e7b864029620927790dfb23b6a5900e13.diff

LOG: [libcxx] Reject month 0 in get_date/__get_month

[libcxx] Reject month 0 in get_date/__get_month

This fixes #47663.

Months in dates should be >= 1 and <= 12.
We parse up to two digits then minus one, because
we want to store this as "months since January"
(0-11).

However we didn't check that the result of that
was not -1. For example if you had (MM/DD/YYYY)
00/21/2022.

Added tests for:
* Failing if month is 0
* Failing if month is 13
* Allowing a leading zero in month e.g. "01"

Note that libc++ and libstdc++ return different
values on parsing failure, and MSVC STL returns
end of stream instead.

Handle the first two by checking for defines, MSVC STL
expects these tests to fail for other reasons already:
https://github.com/microsoft/STL/blob/main/tests/libcxx/expected_results.txt#L372
so not handling that case here.

Reviewed By: #libc, Mordante

Differential Revision: https://reviews.llvm.org/D124175

Added: 
    

Modified: 
    libcxx/include/locale
    libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/locale b/libcxx/include/locale
index 8ff7567d865ed..879f4d9820c96 100644
--- a/libcxx/include/locale
+++ b/libcxx/include/locale
@@ -1925,7 +1925,7 @@ time_get<_CharT, _InputIterator>::__get_month(int& __m,
                                               const ctype<char_type>& __ct) const
 {
     int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
-    if (!(__err & ios_base::failbit) && __t <= 11)
+    if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11)
         __m = __t;
     else
         __err |= ios_base::failbit;

diff  --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp
index 79bcf1b6017ff..a3ae92511d782 100644
--- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp
@@ -104,5 +104,57 @@ int main(int, char**)
         assert(t.tm_year == 109);
         assert(err == std::ios_base::eofbit);
     }
+    // Months must be > 0 and <= 12.
+    {
+        const my_facet f(LOCALE_en_US_UTF_8, 1);
+        const char in[] = "00/21/2022";
+        err = std::ios_base::goodbit;
+        t = std::tm();
+        I i = f.get_date(I(in), I(in+sizeof(in)/sizeof(in[0])-1), ios, err, &t);
+#if _LIBCPP_VERSION
+          // libc++ points to the '/' after the month.
+          assert(base(i) == in+2);
+#else
+          // libstdc++ points to the second character.
+          assert(base(i) == in+1);
+#endif
+        // tm is not modified.
+        assert(t.tm_mon == 0);
+        assert(t.tm_mday == 0);
+        assert(t.tm_year == 0);
+        assert(err == std::ios_base::failbit);
+    }
+    {
+        const my_facet f(LOCALE_en_US_UTF_8, 1);
+        const char in[] = "13/21/2022";
+        err = std::ios_base::goodbit;
+        t = std::tm();
+        I i = f.get_date(I(in), I(in+sizeof(in)/sizeof(in[0])-1), ios, err, &t);
+#if _LIBCPP_VERSION
+          // libc++ points to the '/' after the month.
+          assert(base(i) == in+2);
+#else
+          // libstdc++ points to the second character.
+          assert(base(i) == in+1);
+#endif
+        assert(base(i) == in+2);
+        assert(t.tm_mon == 0);
+        assert(t.tm_mday == 0);
+        assert(t.tm_year == 0);
+        assert(err == std::ios_base::failbit);
+    }
+    // Leading zero is allowed.
+    {
+        const my_facet f(LOCALE_en_US_UTF_8, 1);
+        const char in[] = "03/21/2022";
+        err = std::ios_base::goodbit;
+        t = std::tm();
+        I i = f.get_date(I(in), I(in+sizeof(in)/sizeof(in[0])-1), ios, err, &t);
+        assert(base(i) == in+sizeof(in)/sizeof(in[0])-1);
+        assert(t.tm_mon == 2);
+        assert(t.tm_mday == 21);
+        assert(t.tm_year == 122);
+        assert(err == std::ios_base::eofbit);
+    }
   return 0;
 }


        


More information about the libcxx-commits mailing list