aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/config/locale/generic/codecvt_members.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/config/locale/generic/codecvt_members.cc')
-rw-r--r--libstdc++-v3/config/locale/generic/codecvt_members.cc57
1 files changed, 38 insertions, 19 deletions
diff --git a/libstdc++-v3/config/locale/generic/codecvt_members.cc b/libstdc++-v3/config/locale/generic/codecvt_members.cc
index 183439de4f3..8bdc22779ad 100644
--- a/libstdc++-v3/config/locale/generic/codecvt_members.cc
+++ b/libstdc++-v3/config/locale/generic/codecvt_members.cc
@@ -49,32 +49,51 @@ namespace std
result __ret = ok;
// The conversion must be done using a temporary destination buffer
// since it is not possible to pass the size of the buffer to wcrtomb
- extern_type __buf[MB_LEN_MAX];
- // A temporary state must be used since the result of the last
- // conversion may be thrown away.
state_type __tmp_state(__state);
-
+
// The conversion must be done by calling wcrtomb in a loop rather
// than using wcsrtombs because wcsrtombs assumes that the input is
// zero-terminated.
- while (__from < __from_end && __to < __to_end)
+
+ // Either we can upper bound the total number of external characters to
+ // something smaller than __to_end - __to or the conversion must be done
+ // using a temporary destination buffer since it is not possible to
+ // pass the size of the buffer to wcrtomb
+ if (MB_CUR_MAX * (__from_end - __from) - (__to_end - __to) <= 0)
+ while (__from < __from_end)
+ {
+ const size_t __conv = wcrtomb(__to, *__from, &__tmp_state);
+ if (__conv == static_cast<size_t>(-1))
+ {
+ __ret = error;
+ break;
+ }
+ __state = __tmp_state;
+ __to += __conv;
+ __from++;
+ }
+ else
{
- size_t __conv = wcrtomb(__buf, *__from, &__tmp_state);
- if (__conv == static_cast<size_t>(-1))
- {
- __ret = error;
- break;
- }
- else if (__conv > static_cast<size_t>(__to_end - __to))
+ extern_type __buf[MB_LEN_MAX];
+ while (__from < __from_end && __to < __to_end)
{
- __ret = partial;
- break;
+ const size_t __conv = wcrtomb(__buf, *__from, &__tmp_state);
+ if (__conv == static_cast<size_t>(-1))
+ {
+ __ret = error;
+ break;
+ }
+ else if (__conv > static_cast<size_t>(__to_end - __to))
+ {
+ __ret = partial;
+ break;
+ }
+
+ memcpy(__to, __buf, __conv);
+ __state = __tmp_state;
+ __to += __conv;
+ __from++;
}
-
- memcpy(__to, __buf, __conv);
- __state = __tmp_state;
- __to += __conv;
- __from++;
}
if (__ret == ok && __from < __from_end)