// mbsnrtowcs is *very* fast but stops if encounters NUL characters:
// in case we advance past it and then continue, in a loop.
- // NB: mbsnrtowcs is a GNU extension
+ // NB: mbsnrtowcs is in POSIX.1-2008
+
+ const size_t __to_len = 1024; // Size of alloca'd output buffer
// A dummy internal buffer is needed in order for mbsnrtocws to consider
// its fourth parameter (it wouldn't with NULL as first parameter).
wchar_t* __to = static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t)
- * __max));
+ * __to_len));
while (__from < __end && __max)
{
const extern_type* __from_chunk_end;
const extern_type* __tmp_from = __from;
size_t __conv = mbsnrtowcs(__to, &__from,
__from_chunk_end - __from,
- __max, &__state);
+ __max > __to_len ? __to_len : __max,
+ &__state);
if (__conv == static_cast<size_t>(-1))
{
// In case of error, in order to stop at the exact place we
// mbsnrtowcs is *very* fast but stops if encounters NUL characters:
// in case we advance past it and then continue, in a loop.
- // NB: mbsnrtowcs is a GNU extension
+ // NB: mbsnrtowcs is in POSIX.1-2008
+
+ const size_t __to_len = 1024; // Size of alloca'd output buffer
// A dummy internal buffer is needed in order for mbsnrtocws to consider
// its fourth parameter (it wouldn't with NULL as first parameter).
wchar_t* __to = static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t)
- * __max));
+ * __to_len));
while (__from < __end && __max)
{
const extern_type* __from_chunk_end;
const extern_type* __tmp_from = __from;
size_t __conv = mbsnrtowcs(__to, &__from,
__from_chunk_end - __from,
- __max, &__state);
+ __max > __to_len ? __to_len : __max,
+ &__state);
if (__conv == static_cast<size_t>(-1))
{
// In case of error, in order to stop at the exact place we
--- /dev/null
+// { dg-do run }
+
+// Bug libstdc++/105857 codecvt::do_length causes unexpected buffer overflow
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+int main()
+{
+ std::string s(1050, 'a');
+ typedef std::codecvt<wchar_t, char, std::mbstate_t> Cvt;
+ const Cvt& cvt = std::use_facet<Cvt>(std::locale());
+ const char* from = s.c_str();
+ const char* from_end = s.c_str() + s.size();
+ std::size_t max = std::size_t(-1) / 4 + 2;
+ std::mbstate_t state = std::mbstate_t();
+ int n = cvt.length(state, from, from_end, max);
+ VERIFY( n == s.size() );
+ n = cvt.length(state, from, from_end, 2);
+ VERIFY( n == 2 );
+}