# std::from_chars
     _ZSt10from_charsPKcS0_R[def]St12chars_format;
 
+    # std::__istream_extract(istream&, char*, streamsize)
+    _ZSt17__istream_extractRSiPc[ilx];
+    # std::__istream_extract(wistream&, wchar_t*, streamsize)
+    _ZSt17__istream_extractIwSt11char_traitsIwEEvRSt13basic_istreamIT_T0_EPS3_[ilx];
+
 } GLIBCXX_3.4.28;
 
 # Symbols in the support library (libsupc++) have their own tag.
 
     }
 
   template<typename _CharT, typename _Traits>
-    basic_istream<_CharT, _Traits>&
-    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s)
+    void
+    __istream_extract(basic_istream<_CharT, _Traits>& __in, _CharT* __s,
+                     streamsize __num)
     {
       typedef basic_istream<_CharT, _Traits>           __istream_type;
       typedef basic_streambuf<_CharT, _Traits>          __streambuf_type;
          __try
            {
              // Figure out how many characters to extract.
-             streamsize __num = __in.width();
-             if (__num <= 0)
-               __num = __gnu_cxx::__numeric_traits<streamsize>::__max;
+             streamsize __width = __in.width();
+             if (0 < __width && __width < __num)
+               __num = __width;
 
              const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
 
        __err |= ios_base::failbit;
       if (__err)
        __in.setstate(__err);
-      return __in;
     }
 
   // 27.6.1.4 Standard basic_istream manipulators
   extern template class basic_istream<char>;
   extern template istream& ws(istream&);
   extern template istream& operator>>(istream&, char&);
-  extern template istream& operator>>(istream&, char*);
   extern template istream& operator>>(istream&, unsigned char&);
   extern template istream& operator>>(istream&, signed char&);
-  extern template istream& operator>>(istream&, unsigned char*);
-  extern template istream& operator>>(istream&, signed char*);
 
   extern template istream& istream::_M_extract(unsigned short&);
   extern template istream& istream::_M_extract(unsigned int&);  
   extern template class basic_istream<wchar_t>;
   extern template wistream& ws(wistream&);
   extern template wistream& operator>>(wistream&, wchar_t&);
-  extern template wistream& operator>>(wistream&, wchar_t*);
+  extern template void __istream_extract(wistream&, wchar_t*, streamsize);
 
   extern template wistream& wistream::_M_extract(unsigned short&);
   extern template wistream& wistream::_M_extract(unsigned int&);  
 
     { return (__in >> reinterpret_cast<char&>(__c)); }
   //@}
 
+
+  template<typename _CharT, typename _Traits>
+    void
+    __istream_extract(basic_istream<_CharT, _Traits>&, _CharT*, streamsize);
+
+  void __istream_extract(istream&, char*, streamsize);
+
   //@{
   /**
    *  @brief  Character string extractors
    *  @param  __in  An input stream.
-   *  @param  __s  A pointer to a character array.
+   *  @param  __s  A character array (or a pointer to an array before C++20).
    *  @return  __in
    *
    *  Behaves like one of the formatted arithmetic extractors described in
-   *  std::basic_istream.  After constructing a sentry object with good
-   *  status, this function extracts up to @c n characters and stores them
-   *  into the array starting at @a __s.  @c n is defined as:
+   *  `std::basic_istream`.  After constructing a sentry object with good
+   *  status, this function extracts up to `n` characters and stores them
+   *  into the array `__s`.  `n` is defined as:
    *
-   *  - if @c width() is greater than zero, @c n is width() otherwise
-   *  - @c n is <em>the number of elements of the largest array of *
-   *  - @c char_type that can store a terminating @c eos.</em>
-   *  - [27.6.1.2.3]/6
+   *  - if `width()` is greater than zero, `n` is `min(width(), n)`
+   *  - otherwise `n` is the number of elements of the array
+   *  - (before C++20 the pointer is assumed to point to an array of
+   *  - the largest possible size for an array of `char_type`).
    *
    *  Characters are extracted and stored until one of the following happens:
-   *  - @c n-1 characters are stored
+   *  - `n - 1` characters are stored
    *  - EOF is reached
    *  - the next character is whitespace according to the current locale
-   *  - the next character is a null byte (i.e., @c charT() )
+   *  - the next character is a null byte (i.e., `charT()`)
    *
-   *  @c width(0) is then called for the input stream.
+   *  `width(0)` is then called for the input stream.
    *
    *  If no characters are extracted, sets failbit.
   */
-  template<typename _CharT, typename _Traits>
-    basic_istream<_CharT, _Traits>&
-    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s);
 
-  // Explicit specialization declaration, defined in src/istream.cc.
-  template<>
-    basic_istream<char>&
-    operator>>(basic_istream<char>& __in, char* __s);
+#if __cplusplus <= 201703L
+  template<typename _CharT, typename _Traits>
+    inline basic_istream<_CharT, _Traits>&
+    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s)
+    {
+      streamsize __n = __builtin_object_size(__s, 2) / sizeof(_CharT);
+      if (__n == 0)
+       __n = __gnu_cxx::__numeric_traits<streamsize>::__max / sizeof(_CharT);
+      std::__istream_extract(__in, __s, __n);
+      return __in;
+    }
 
   template<class _Traits>
     inline basic_istream<char, _Traits>&
     inline basic_istream<char, _Traits>&
     operator>>(basic_istream<char, _Traits>& __in, signed char* __s)
     { return (__in >> reinterpret_cast<char*>(__s)); }
+#else
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2499. operator>>(istream&, char*) makes it hard to avoid buffer overflows
+  template<typename _CharT, typename _Traits, size_t _Num>
+    inline basic_istream<_CharT, _Traits>&
+    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT (&__s)[_Num])
+    {
+      static_assert(_Num <= __gnu_cxx::__numeric_traits<streamsize>::__max);
+      std::__istream_extract(__in, __s, _Num);
+      return __in;
+    }
+
+  template<class _Traits, size_t _Num>
+    inline basic_istream<char, _Traits>&
+    operator>>(basic_istream<char, _Traits>& __in, unsigned char (&__s)[_Num])
+    { return __in >> reinterpret_cast<char(&)[_Num]>(__s); }
+
+  template<class _Traits, size_t _Num>
+    inline basic_istream<char, _Traits>&
+    operator>>(basic_istream<char, _Traits>& __in, signed char (&__s)[_Num])
+    { return __in >> reinterpret_cast<char(&)[_Num]>(__s); }
+#endif
   //@}
 
   /**
 
                                               void>::__type
         advance(istreambuf_iterator<_CharT2>&, _Distance);
 
-      template<typename _CharT2, typename _Traits2>
-        friend basic_istream<_CharT2, _Traits2>&
-        operator>>(basic_istream<_CharT2, _Traits2>&, _CharT2*);
+      friend void __istream_extract(istream&, char*, streamsize);
 
       template<typename _CharT2, typename _Traits2, typename _Alloc>
         friend basic_istream<_CharT2, _Traits2>&
 
   template istream& operator>>(istream&, char&);
   template istream& operator>>(istream&, unsigned char&);
   template istream& operator>>(istream&, signed char&);
+
+#if ! _GLIBCXX_INLINE_VERSION
+  // XXX GLIBCXX_ABI Deprecated
   template istream& operator>>(istream&, char*);
   template istream& operator>>(istream&, unsigned char*);
   template istream& operator>>(istream&, signed char*);
+#endif
 
   template istream& operator>>(istream&, _Setfill<char>);
   template istream& operator>>(istream&, _Setiosflags);
   template class basic_istream<wchar_t>;
   template wistream& ws(wistream&);
   template wistream& operator>>(wistream&, wchar_t&);
+  template void __istream_extract(wistream&, wchar_t*, streamsize);
+
+#if ! _GLIBCXX_INLINE_VERSION
+  // XXX GLIBCXX_ABI Deprecated
   template wistream& operator>>(wistream&, wchar_t*);
+#endif
 
   template wistream& operator>>(wistream&, _Setfill<wchar_t>);
   template wistream& operator>>(wistream&, _Setiosflags);
 
       return *this;
     }
 
-  template<>
-    basic_istream<char>&
-    operator>>(basic_istream<char>& __in, char* __s)
+    void
+    __istream_extract(istream& __in, char* __s, streamsize __num)
     {
       typedef basic_istream<char>              __istream_type;
       typedef __istream_type::int_type         __int_type;
          __try
            {
              // Figure out how many characters to extract.
-             streamsize __num = __in.width();
-             if (__num <= 0)
-               __num = __gnu_cxx::__numeric_traits<streamsize>::__max;
+             streamsize __width = __in.width();
+             if (0 < __width && __width < __num)
+               __num = __width;
 
              const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
 
        __err |= ios_base::failbit;
       if (__err)
        __in.setstate(__err);
-      return __in;
     }
 
 #ifdef _GLIBCXX_USE_WCHAR_T
 
 
   // template<_CharT, _Traits>
   //  basic_istream& operator>>(istream&, _CharT*)
-  int n = 20;
+  const int n = 20;
   char array1[n];
   typedef std::ios::traits_type ctraits_type;
 
 
 
 // 27.6.1.2.3 basic_istream::operator>>
 
+// { dg-do run { target { ! c++20 } } }
 // { dg-require-fileio "" }
 
 #include <istream>
 
   testthrow(c);
   testthrow(uc);
   testthrow(sc);
+#if __cplusplus <= 201703L
   testthrow(cp);
   testthrow(scp);
   testthrow(ucp);
+#endif
 
   return 0;
 }
 
   sstr >> str;
 
   // 2
-  pod_char*  chr = 0;
+  pod_char  chr[1];
   sstr >> chr;
 
   // 3
 
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// LWG 2499
+// operator>>(basic_istream&, CharT*) makes it hard to avoid buffer overflows
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+template<typename T>
+void
+test(std::basic_istream<char, T>& in)
+{
+  char pc[3];
+  in >> pc;
+  VERIFY( in.good() );
+  VERIFY( pc[0] == 'a' && pc[1] == 'b' && pc[2] == '\0' );
+
+  signed char sc[4];
+  in >> sc;
+  VERIFY( in.good() );
+  VERIFY( sc[0] == 'c' && sc[1] == 'd' && sc[2] == 'e' && sc[3] ==  '\0' );
+
+  unsigned char uc[4];
+  in >> uc;
+  VERIFY( in.good() );
+  VERIFY( uc[0] == 'f' && uc[1] == 'g' && uc[2] == 'h' && uc[3] ==  '\0' );
+
+  pc[2] = '#';
+  in >> pc;
+  VERIFY( in.good() );
+  VERIFY( pc[0] == 'i' && pc[1] == '\0' && pc[2] == '#' );
+
+  in >> pc;
+  VERIFY( in.good() );
+  VERIFY( pc[0] == 'j' && pc[1] == 'k' && pc[2] == '\0' );
+
+  pc[2] = '#';
+  in >> pc;
+  VERIFY( in.eof() );
+  VERIFY( pc[0] == 'l' && pc[1] == '\0' && pc[2] == '#' );
+}
+
+void
+test01()
+{
+  std::istringstream in("abcdefghi jk l");
+  test(in);
+}
+
+void
+test02()
+{
+  struct CT : std::char_traits<char> { };
+  std::basic_istringstream<char, CT> in("abcdefghi jk l");
+  test(in);
+}
+
+int main()
+{
+  test01();
+  test02();
+}
 
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// LWG 2499
+// operator>>(basic_istream&, CharT*) makes it hard to avoid buffer overflows
+
+#include <istream>
+
+void
+test01(std::istream& in, char* pc, signed char* sc, unsigned char* uc)
+{
+  in >> pc; // { dg-error "here" }
+  in >> sc; // { dg-error "here" }
+  in >> uc; // { dg-error "here" }
+}
+
+struct CT : std::char_traits<char> { };
+
+void
+test02(std::basic_istream<char, CT>& in, char* pc, signed char* sc,
+       unsigned char* uc)
+{
+  in >> pc; // { dg-error "here" }
+  in >> sc; // { dg-error "here" }
+  in >> uc; // { dg-error "here" }
+}
+
+// { dg-excess-errors "" }
 
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-O2 -std=gnu++98" }
+// { dg-do run }
+
+// This test checks that operator>> will avoid a buffer overflow when
+// reading into a buffer with a size that is known at compile time.
+
+// Since C++20 this is guaranteed (see LWG 2499), for previous standards
+// we try to check the buffer size as an extension (which depends on -O2).
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::istringstream in("foolish child");
+  char pc[5];
+  in >> pc;
+  VERIFY( in.good() );
+  VERIFY( std::string(pc) == "fool" );
+}
+
+void
+test02()
+{
+  std::istringstream in("foolish");
+  signed char sc[5];
+  in >> sc;
+  VERIFY( in.good() );
+  VERIFY( std::string((const char*)sc) == "fool" );
+}
+
+void
+test03()
+{
+  std::istringstream in("foolish");
+  unsigned char uc[5];
+  in >> uc;
+  VERIFY( in.good() );
+  VERIFY( std::string((const char*)uc) == "fool" );
+}
+
+int
+main()
+{
+  test01();
+}
 
 
   // template<_CharT, _Traits>
   //  basic_istream& operator>>(istream&, _CharT*)
-  int n = 20;
+  const int n = 20;
   wchar_t array1[n];
   typedef std::wios::traits_type ctraits_type;
 
 
 // 27.6.1.2.3 basic_istream::operator>>
 
 // { dg-options "-DMAX_SIZE=466" { target simulator } }
+// { dg-do run { target { ! c++20 } } }
 // { dg-require-fileio "" }
 
 #ifndef MAX_SIZE
 
   wchar_t* cp = &c;
 
   testthrow(c);
+#if __cplusplus <= 201703L
   testthrow(cp);
+#endif
 
   return 0;
 }
 
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// LWG 2499
+// operator>>(basic_istream&, CharT*) makes it hard to avoid buffer overflows
+
+#include <sstream>
+#include <testsuite_hooks.h>
+
+template<typename T>
+void
+test(std::basic_istream<wchar_t, T>& in)
+{
+  wchar_t wc[3];
+  in >> wc;
+  VERIFY( in.good() );
+  VERIFY( wc[0] == L'a' && wc[1] == L'b' && wc[2] == L'\0' );
+
+  wc[2] = L'#';
+  in >> wc;
+  VERIFY( in.good() );
+  VERIFY( wc[0] == L'c' && wc[1] == L'\0' && wc[2] == L'#' );
+
+  in >> wc;
+  VERIFY( in.good() );
+  VERIFY( wc[0] == L'd' && wc[1] == L'\0' && wc[2] == L'#' );
+
+  wc[2] = L'#';
+  in >> wc;
+  VERIFY( in.eof() );
+  VERIFY( wc[0] == L'e' && wc[1] == L'\0' && wc[2] == L'#' );
+}
+
+void
+test01()
+{
+  std::wistringstream in(L"abc d e");
+  test(in);
+}
+
+void
+test02()
+{
+  struct WT : std::char_traits<wchar_t> { };
+  std::basic_istringstream<wchar_t, WT> in(L"abc d e");
+  test(in);
+}
+
+int main()
+{
+  test01();
+  test02();
+}
 
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// LWG 2499
+// operator>>(basic_istream&, CharT*) makes it hard to avoid buffer overflows
+
+#include <istream>
+
+void
+test01(std::wistream& in, wchar_t* wc)
+{
+  in >> wc; // { dg-error "here" }
+}
+
+struct WT : std::char_traits<wchar_t> { };
+
+void
+test02(std::basic_istream<wchar_t, WT>& in, wchar_t* wc)
+{
+  in >> wc; // { dg-error "here" }
+}
+
+// { dg-excess-errors "" }