This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix risks of buf overflow in money_put


Nathan Myers wrote:

> > IMO, the former can be dealt with in full generality only by enlarging
> > the buffer to the real maximum expected size of the printed string.
> > The latter, luckily, is fixed much more easily, since, in fact, the
> > actual size of the integer part is known at that point.
>
> Seems you shouldn't need a separate staging buffer for the string version.
> Maybe the code is simpler that way.

Good point. Indeed, my personal opinion, is that in general we could probably
dispense with a few buffers.

However, the current solution has some advantages: do_put(long double) uses
do_put(string) and when the latter is used the much bigger buffer of the former
is not allocated. Also, the buffer in do_put(string) is allocated only when
grouping is actually used.

> It think the patch got damaged by your mailer.

Yes, some long lines got wrongly wrapped, sorry. I'm attaching the patch
again here.

Thanks, Paolo.

///////////////////

diff -urN libstdc++-v3-orig/include/bits/locale_facets.tcc
libstdc++-v3/include/bits/locale_facets.tcc
--- libstdc++-v3-orig/include/bits/locale_facets.tcc Mon Mar 11 00:51:31 2002
+++ libstdc++-v3/include/bits/locale_facets.tcc Sun Mar 17 02:12:13 2002
@@ -1110,8 +1110,10 @@
     long double __units) const
     {
       const locale __loc = __io.getloc();
-      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      const int __n = numeric_limits<long double>::digits10;
+      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+      // 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);
@@ -1206,7 +1208,7 @@
                   : __mpf.thousands_sep();
     const char* __gbeg = __grouping.c_str();
     const char* __gend = __gbeg + __grouping.size();
-    const int __n = numeric_limits<long double>::digits10 * 2;
+    const int __n = (__end - __beg) * 2;
     _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
     _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg,
           __gend, __beg, __end);
diff -urN libstdc++-v3-orig/testsuite/22_locale/money_put_members_char.cc
libstdc++-v3/testsuite/22_locale/money_put_members_char.cc
--- libstdc++-v3-orig/testsuite/22_locale/money_put_members_char.cc Wed Feb 20 22:06:40
2002
+++ libstdc++-v3/testsuite/22_locale/money_put_members_char.cc Sun Mar 17 01:37:23 2002
@@ -226,7 +226,7 @@
   oss.setf(ios_base::showbase);

   oss.str(empty);
- iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
+  iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
   string result3 = oss.str();
   VERIFY( result3 == "7.200.000.000,00 DEM ");

@@ -341,6 +341,33 @@
   VERIFY( fmt.str() == "*(1,234.56)" );
 }

+struct My_money_io_2 : public std::moneypunct<char,false>
+{
+  char_type do_thousands_sep() const { return ','; }
+  std::string do_grouping() const { return "\001"; }
+};
+
+// Make sure we can output a very big amount of money (with grouping too).
+void test06()
+{
+  using namespace std;
+  typedef ostreambuf_iterator<char> OutIt;
+
+  locale loc(locale::classic(), new My_money_io_2);
+
+  bool intl = false;
+
+  long double val = 1e50L;
+  const money_put<char,OutIt>& mp  =
+    use_facet<money_put<char, OutIt> >(loc);
+
+  ostringstream fmt;
+  fmt.imbue(loc);
+  OutIt out(fmt);
+  mp.put(out,intl,fmt,'*',val);
+  VERIFY( fmt );
+}
+
 int main()
 {
   test01();
@@ -348,5 +375,6 @@
   test03();
   test04();
   test05();
+  test06();
   return 0;
 }
diff -urN libstdc++-v3-orig/testsuite/22_locale/money_put_members_wchar_t.cc
libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc
--- libstdc++-v3-orig/testsuite/22_locale/money_put_members_wchar_t.cc Wed Feb 20 22:06:40
2002
+++ libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc Sun Mar 17 01:42:42 2002

@@ -226,7 +226,7 @@
   oss.setf(ios_base::showbase);

   oss.str(empty);
- iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
+  iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, ' ', digits1);
   wstring result3 = oss.str();
   VERIFY( result3 == L"7.200.000.000,00 DEM ");

@@ -340,6 +340,33 @@
   mp.put(out,intl,fmt,L'*',val);
   VERIFY( fmt.str() == L"*(1,234.56)" );
 }
+
+struct My_money_io_2 : public std::moneypunct<wchar_t,false>
+{
+  char_type do_thousands_sep() const { return L','; }
+  std::string do_grouping() const { return "\001"; }
+};
+
+// Make sure we can output a very big amount of money (with grouping too).
+void test06()
+{
+  using namespace std;
+  typedef ostreambuf_iterator<wchar_t> OutIt;
+
+  locale loc(locale::classic(), new My_money_io_2);
+
+  bool intl = false;
+
+  long double val = 1e50L;
+  const money_put<wchar_t,OutIt>& mp  =
+    use_facet<money_put<wchar_t, OutIt> >(loc);
+
+  wostringstream fmt;
+  fmt.imbue(loc);
+  OutIt out(fmt);
+  mp.put(out,intl,fmt,'*',val);
+  VERIFY( fmt );
+}
 #endif

 int main()
@@ -350,6 +377,7 @@
   test03();
   test04();
   test05();
+  test06();
 #endif
   return 0;
 }



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]