Package: g++-mingw-w64-i686
Version: 4.6.3-14+8+nmu1
Severity: normal
Tags: patch
Dear Maintainer,
The following program crashes when built with x86_64-w64-mingw32-g++ or
i686-w64-mingw32-g++:
#include <iostream>
int main() {
std::cout.setf(std::ios::fixed);
std::cout << 1e300 << "\n";
return 0;
}
The underlying cause is an assumption that snprintf never returns -1. In fact,
on Windows, the platform snprintf returns -1 when the buffer is not big
enough, which leads to (A) calling alloca(-1) and (B) calling std::widen
with fin < st, either one of which is probably enough to lead to a
crash.
The patch shown below fixes several locations in libstdc++ where a
negative return value from snprintf was not properly handled.
As far as I'm aware, this bug also exists upstream, but I have not filed
it there.
-- System Information:
Debian Release: 7.3
APT prefers stable-updates
APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 3.2.0-4-amd64 (SMP w/12 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages g++-mingw-w64-i686 depends on:
ii gcc-mingw-w64-base 4.6.3-14+8+nmu1
ii gcc-mingw-w64-i686 4.6.3-14+8+nmu1
ii libc6 2.13-38
ii libgmp10 2:5.0.5+dfsg-2
ii libmpc2 0.9-4
ii libmpfr4 3.1.0-5
ii libstdc++6-4.6-dev 4.6.3-14
ii zlib1g 1:1.2.7.dfsg-13
g++-mingw-w64-i686 recommends no packages.
Versions of packages g++-mingw-w64-i686 suggests:
pn gcc-4.6-locales <none>
-- no debconf information
diff -Nru gcc-mingw-w64-8/debian/changelog gcc-mingw-w64-8+nmu1/debian/changelog
--- gcc-mingw-w64-8/debian/changelog 2012-12-12 00:30:21.000000000 -0600
+++ gcc-mingw-w64-8+nmu1/debian/changelog 2014-01-28 09:52:09.000000000
-0600
@@ -1,3 +1,10 @@
+gcc-mingw-w64 (8+nmu1) stable; urgency=low
+
+ * Non-maintainer upload.
+ * Fix crash in ostream with ios::fixed and large numbers (PR28891)
+
+ -- Jeff Epler <[email protected]> Tue, 28 Jan 2014 09:16:10 -0600
+
gcc-mingw-w64 (8) unstable; urgency=low
* Replace /usr/share/doc/gcc-mingw32 with a symlink when necessary
diff -Nru gcc-mingw-w64-8/debian/patches/snprintf-minusone.patch
gcc-mingw-w64-8+nmu1/debian/patches/snprintf-minusone.patch
--- gcc-mingw-w64-8/debian/patches/snprintf-minusone.patch 1969-12-31
18:00:00.000000000 -0600
+++ gcc-mingw-w64-8+nmu1/debian/patches/snprintf-minusone.patch 2014-01-28
09:07:07.000000000 -0600
@@ -0,0 +1,60 @@
+@@ -, +, @@
+ .../libstdc++-v3/include/bits/locale_facets.tcc | 14 ++++++++++++++
+ .../include/bits/locale_facets_nonio.tcc | 10 ++++++++++
+ 2 files changed, 24 insertions(+), 0 deletions(-)
+--- a/gcc/src/libstdc++-v3/include/bits/locale_facets.tcc
++++ a/gcc/src/libstdc++-v3/include/bits/locale_facets.tcc
+@@ -995,6 +995,17 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ __fbuf, __prec, __v);
+
++ // If snprintf returned negative, we have to use a buffer guaranteed big
++ // enough for any value
++ if (__len < 0)
++ {
++ const bool __fixed = __io.flags() & ios_base::fixed;
++ const int __max_exp =
++ __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10;
++ __len = __fixed ? __max_exp + __prec + 4
++ : __max_digits * 2 + __prec;
++ }
++
+ // If the buffer was not large enough, try again with the correct size.
+ if (__len >= __cs_size)
+ {
+@@ -1002,6 +1013,9 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
+ __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ __fbuf, __prec, __v);
++ // guard against a further error return from snprintf, which should
++ // not have been possible
++ if(__len < 0) __len = 0;
+ }
+ #else
+ // Consider the possibility of long ios_base::fixed outputs
+--- a/gcc/src/libstdc++-v3/include/bits/locale_facets_nonio.tcc
++++ a/gcc/src/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+@@ -578,6 +578,13 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
+ // 328. Bad sprintf format modifier in money_put<>::do_put()
+ int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ "%.*Lf", 0, __units);
++ // If snprintf returned negative, we have to use a buffer guaranteed big
++ // enough for any value
++ if (__len < 0)
++ {
++ __len = __gnu_cxx::__numeric_traits<long double>::__max_exponent10 +
3;
++ }
++
+ // If the buffer was not large enough, try again with the correct size.
+ if (__len >= __cs_size)
+ {
+@@ -585,6 +592,9 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
+ __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+ __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
+ "%.*Lf", 0, __units);
++ // guard against a further error return from snprintf, which should
++ // not have been possible
++ if(__len < 0) __len = 0;
+ }
+ #else
+ // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
diff -Nru gcc-mingw-w64-8/debian/rules gcc-mingw-w64-8+nmu1/debian/rules
--- gcc-mingw-w64-8/debian/rules 2012-10-17 00:03:49.000000000 -0500
+++ gcc-mingw-w64-8+nmu1/debian/rules 2014-01-28 09:15:06.000000000 -0600
@@ -144,6 +144,8 @@
patch -p1 -d$(upstream_dir) < debian/patches/cpp-intrinsics.patch
# Spelling fixes
patch -p2 -d$(upstream_dir) < debian/patches/spelling-fixes-code.patch
+ # Fix snprintf use in libstdc++ (dsndata.com#11278)
+ patch -p3 -d$(upstream_dir) < debian/patches/snprintf-minusone.patch
touch $@
configure: configure-stamp
Binary files
/dev/shm/ccache/ljcEmTK90v/gcc-mingw-w64-8/gcc-mingw-w64-build-deps_1.0_all.deb
and
/dev/shm/ccache/T2TJfEEzLq/gcc-mingw-w64-8+nmu1/gcc-mingw-w64-build-deps_1.0_all.deb
differ
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]