[libcxx-commits] [libcxx] [libc++] Fix num_get base parsing (PR #170460)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Wed Dec 3 02:48:17 PST 2025


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/170460

None

>From c2ff701fe3d63e75ec56f4a63a18cfdc32c91648 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 3 Dec 2025 11:47:59 +0100
Subject: [PATCH] [libc++] Fix num_get base parsing

---
 libcxx/include/__locale_dir/num.h             |  2 +
 .../facet.num.get.members/get_long.pass.cpp   | 96 +++++++++++++++++++
 2 files changed, 98 insertions(+)

diff --git a/libcxx/include/__locale_dir/num.h b/libcxx/include/__locale_dir/num.h
index 98b8eb0c600f5..b7ea02e7cb7f7 100644
--- a/libcxx/include/__locale_dir/num.h
+++ b/libcxx/include/__locale_dir/num.h
@@ -436,6 +436,7 @@ class num_get : public locale::facet, private __num_get<_CharT> {
         ++__first;
         if (__first == __last) {
           __err |= ios_base::eofbit;
+          __v = 0;
           return __first;
         }
         // __c2 == 'x' || __c2 == 'X'
@@ -444,6 +445,7 @@ class num_get : public locale::facet, private __num_get<_CharT> {
           ++__first;
         } else {
           __base = 8;
+          __parsed_num = true; // We only swallowed '0', so we've started to parse a number
         }
       } else {
         __base = 10;
diff --git a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp
index a110aae2db11b..45b034833fecc 100644
--- a/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long.pass.cpp
@@ -670,5 +670,101 @@ int main(int, char**)
       assert(v == std::numeric_limits<long>::min());
     }
 
+  { // Check that auto-detection of the base works properly
+    ios.flags(ios.flags() & ~std::ios::basefield);
+    { // zeroes
+      {
+        v                          = -1;
+        const char str[]           = "0";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 1), ios, err, v);
+        assert(base(iter) == str + 1);
+        assert(err == ios.eofbit);
+        assert(v == 0);
+      }
+      {
+        v                          = -1;
+        const char str[]           = "00";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
+        assert(base(iter) == str + 2);
+        assert(err == ios.eofbit);
+        assert(v == 0);
+      }
+      {
+        v                          = -1;
+        const char str[]           = "0x0";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+        assert(base(iter) == str + 3);
+        assert(err == ios.eofbit);
+        assert(v == 0);
+      }
+      {
+        v                          = -1;
+        const char str[]           = "0X0";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+        assert(base(iter) == str + 3);
+        assert(err == ios.eofbit);
+        assert(v == 0);
+      }
+    }
+    { // first character after base is out of range
+      {
+        v                          = -1;
+        const char str[]           = "08";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
+        assert(base(iter) == str + 1);
+        assert(err == ios.goodbit);
+        assert(v == 0);
+      }
+      {
+        v                          = -1;
+        const char str[]           = "1a";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 2), ios, err, v);
+        assert(base(iter) == str + 1);
+        assert(err == ios.goodbit);
+        assert(v == 1);
+      }
+      {
+        v                          = -1;
+        const char str[]           = "0xg";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+        assert(base(iter) == str + 2);
+        assert(err == ios.failbit);
+        assert(v == 0);
+      }
+      {
+        v                          = -1;
+        const char str[]           = "0Xg";
+        std::ios_base::iostate err = ios.goodbit;
+
+        cpp17_input_iterator<const char*> iter =
+            f.get(cpp17_input_iterator<const char*>(str), cpp17_input_iterator<const char*>(str + 3), ios, err, v);
+        assert(base(iter) == str + 2);
+        assert(err == ios.failbit);
+        assert(v == 0);
+      }
+    }
+  }
+
   return 0;
 }



More information about the libcxx-commits mailing list