aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Carlini <pcarlini@unitus.it>2002-03-19 23:33:06 +0100
committerPaolo Carlini <paolo@gcc.gnu.org>2002-03-19 22:33:06 +0000
commit6d8e16a4637fe1b646260485882f668b0a736cf1 (patch)
tree9f539fec7bb1f4014bbdd77a0b9b316e9b070056
parent1e82682ba4cdba6ec02c26aae84ed7a9ce5a1003 (diff)
downloadgcc-6d8e16a4637fe1b646260485882f668b0a736cf1.zip
gcc-6d8e16a4637fe1b646260485882f668b0a736cf1.tar.gz
gcc-6d8e16a4637fe1b646260485882f668b0a736cf1.tar.bz2
locale-inst.cc (__convert_from_v): Add an additional __size parameter in the declarations.
2002-03-19 Paolo Carlini <pcarlini@unitus.it> Ulrich Drepper <drepper@redhat.com> * src/locale-inst.cc (__convert_from_v): Add an additional __size parameter in the declarations. * include/bits/locale_facets.tcc (__convert_from_v): When available (that is, _GLIBCPP_USE_C99 defined) use snprintf instead of sprintf. (num_put::_M_convert_float): Depending on _GLIBCPP_USE_C99 being defined or not, call and use __convert_from_v in the appropriate way. (num_put::_M_convert_int): Same here. (money_put::do_put(long double)): Same here. Co-Authored-By: Ulrich Drepper <drepper@redhat.com> From-SVN: r51050
-rw-r--r--libstdc++-v3/ChangeLog14
-rw-r--r--libstdc++-v3/include/bits/locale_facets.tcc123
-rw-r--r--libstdc++-v3/src/locale-inst.cc12
3 files changed, 117 insertions, 32 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 507821e..eca9f6f 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,17 @@
+2002-03-19 Paolo Carlini <pcarlini@unitus.it>
+ Ulrich Drepper <drepper@redhat.com>
+
+ * src/locale-inst.cc (__convert_from_v): Add an additional
+ __size parameter in the declarations.
+ * include/bits/locale_facets.tcc
+ (__convert_from_v): When available (that is,
+ _GLIBCPP_USE_C99 defined) use snprintf instead of sprintf.
+ (num_put::_M_convert_float): Depending on _GLIBCPP_USE_C99
+ being defined or not, call and use __convert_from_v in the
+ appropriate way.
+ (num_put::_M_convert_int): Same here.
+ (money_put::do_put(long double)): Same here.
+
2002-03-19 Phil Edwards <pme@gcc.gnu.org>
* docs/html/faq/index.html (#3.6): Rewrap and close <a href> tags.
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index f2a1789..30e6632 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -592,16 +592,15 @@ namespace std
return __beg;
}
-
- // The following code uses sprintf() to convert floating point
- // values for insertion into a stream. An optimization would be to
- // replace sprintf() with code that works directly on a wide buffer
- // and then use __pad to do the padding. It would be good
- // to replace sprintf() anyway to avoid accidental buffer overruns
- // and to gain back the efficiency that C++ provides by knowing up
- // front the type of the values to insert. This implementation
- // follows the C++ standard fairly directly as outlined in 22.2.2.2
- // [lib.locale.num.put]
+ // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99
+ // is not defined) to convert floating point values for insertion into a
+ // stream. An optimization would be to replace them with code that works
+ // directly on a wide buffer and then use __pad to do the padding.
+ // It would be good to replace them anyway to gain back the efficiency
+ // that C++ provides by knowing up front the type of the values to insert.
+ // Also, sprintf is dangerous since may lead to accidental buffer overruns.
+ // This implementation follows the C++ standard fairly directly as
+ // outlined in 22.2.2.2 [lib.locale.num.put]
template<typename _CharT, typename _OutIter>
template<typename _ValueT>
_OutIter
@@ -613,13 +612,38 @@ namespace std
// we get the full available precision.
const int __max_digits = numeric_limits<_ValueT>::digits10 + 1;
streamsize __prec = __io.precision();
- // Protect against sprintf() buffer overflows.
+
if (__prec > static_cast<streamsize>(__max_digits))
__prec = static_cast<streamsize>(__max_digits);
// Long enough for the max format spec.
char __fbuf[16];
+ // [22.2.2.2.2] Stage 1, numeric conversion to character.
+ int __len;
+#ifdef _GLIBCPP_USE_C99
+ // First try a buffer perhaps big enough (for sure sufficient for
+ // non-ios_base::fixed outputs)
+ int __cs_size = __max_digits * 3;
+ char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+
+ const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
+ if (__fp)
+ __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale, __prec);
+ else
+ __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
+
+ // If the buffer was not large enough, try again with the correct size.
+ if (__len >= __cs_size)
+ {
+ __cs_size = __len + 1;
+ __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+ if (__fp)
+ __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale, __prec);
+ else
+ __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
+ }
+#else
// Consider the possibility of long ios_base::fixed outputs
const bool __fixed = __io.flags() & ios_base::fixed;
const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
@@ -632,12 +656,11 @@ namespace std
: __max_digits * 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- int __len;
- // [22.2.2.2.2] Stage 1, numeric conversion to character.
if (_S_format_float(__io, __fbuf, __mod, __prec))
- __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale, __prec);
+ __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
else
- __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
+ __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
+#endif
return _M_widen_float(__s, __io, __fill, __cs, __len);
}
@@ -649,13 +672,28 @@ namespace std
char __modl, _ValueT __v) const
{
// [22.2.2.2.2] Stage 1, numeric conversion to character.
- // Leave room for "+/-," "0x," and commas. This size is
- // arbitrary, but should work.
- char __cs[64];
+
// Long enough for the max format spec.
char __fbuf[16];
_S_format_int(__io, __fbuf, __mod, __modl);
- int __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
+#ifdef _GLIBCPP_USE_C99
+ // First try a buffer perhaps big enough.
+ int __cs_size = 64;
+ char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+ int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
+ // If the buffer was not large enough, try again with the correct size.
+ if (__len >= __cs_size)
+ {
+ __cs_size = __len + 1;
+ __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+ __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
+ }
+#else
+ // Leave room for "+/-," "0x," and commas. This size is
+ // arbitrary, but should be largely sufficient.
+ char __cs[128];
+ int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
+#endif
return _M_widen_int(__s, __io, __fill, __cs, __len);
}
@@ -1111,12 +1149,26 @@ namespace std
{
const locale __loc = __io.getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+#ifdef _GLIBCPP_USE_C99
+ // First try a buffer perhaps big enough.
+ int __cs_size = 64;
+ char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __cs_size));
+ int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, _S_c_locale);
+ // If the buffer was not large enough, try again with the correct size.
+ if (__len >= __cs_size)
+ {
+ __cs_size = __len + 1;
+ __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __cs_size));
+ __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, _S_c_locale);
+ }
+#else
// max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
// decimal digit, '\0'.
- const int __n = numeric_limits<long double>::max_exponent10 + 5;
- char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
- _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
- int __len = __convert_from_v(__cs, "%.01Lf", __units, _S_c_locale);
+ const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
+ char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __cs_size));
+ int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale);
+#endif
+ _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size));
__ctype.widen(__cs, __cs + __len, __ws);
string_type __digits(__ws);
return this->do_put(__s, __intl, __io, __fill, __digits);
@@ -1894,20 +1946,39 @@ namespace std
const __c_locale& __cloc, int __base = 10);
// Convert numeric value of type _Tv to string and return length of string.
+ // If snprintf is available use it, otherwise fall back to the unsafe sprintf
+ // which, in general, can be dangerous and should be avoided.
+#ifdef _GLIBCPP_USE_C99
+ template<typename _Tv>
+ int
+ __convert_from_v(char* __out, const int __size, const char* __fmt,
+ _Tv __v, const __c_locale&, int __prec = -1)
+ {
+ int __ret;
+ const char* __old = setlocale(LC_ALL, "C");
+ if (__prec >= 0)
+ __ret = snprintf(__out, __size, __fmt, __prec, __v);
+ else
+ __ret = snprintf(__out, __size, __fmt, __v);
+ setlocale(LC_ALL, __old);
+ return __ret;
+ }
+#else
template<typename _Tv>
int
- __convert_from_v(char* __out, const char* __fmt, _Tv __v,
+ __convert_from_v(char* __out, const int, const char* __fmt, _Tv __v,
const __c_locale&, int __prec = -1)
{
int __ret;
const char* __old = setlocale(LC_ALL, "C");
if (__prec >= 0)
- __ret = sprintf(__out, __fmt, __prec, __v);
+ __ret = sprintf(__out, __fmt, __prec, __v);
else
- __ret = sprintf(__out, __fmt, __v);
+ __ret = sprintf(__out, __fmt, __v);
setlocale(LC_ALL, __old);
return __ret;
}
+#endif
// Construct correctly padded string, as per 22.2.2.2.2
// Assumes
diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc
index 9e449e6..8662c10 100644
--- a/libstdc++-v3/src/locale-inst.cc
+++ b/libstdc++-v3/src/locale-inst.cc
@@ -461,28 +461,28 @@ namespace std
template
int
- __convert_from_v(char*, const char*, double, const __c_locale&, int);
+ __convert_from_v(char*, const int, const char*, double, const __c_locale&, int);
template
int
- __convert_from_v(char*, const char*, long double, const __c_locale&, int);
+ __convert_from_v(char*, const int, const char*, long double, const __c_locale&, int);
template
int
- __convert_from_v(char*, const char*, long, const __c_locale&, int);
+ __convert_from_v(char*, const int, const char*, long, const __c_locale&, int);
template
int
- __convert_from_v(char*, const char*, unsigned long,
+ __convert_from_v(char*, const int, const char*, unsigned long,
const __c_locale&, int);
template
int
- __convert_from_v(char*, const char*, long long, const __c_locale&, int);
+ __convert_from_v(char*, const int, const char*, long long, const __c_locale&, int);
template
int
- __convert_from_v(char*, const char*, unsigned long long,
+ __convert_from_v(char*, const int, const char*, unsigned long long,
const __c_locale&, int);
template