Farid Zaripov
Thu, 13 Sep 2007 10:07:00 -0700
The 22.locale.money.put.cpp test fails on MSVC 7.1 (15s build type)
with buffer overrun error due to bad code generation.
Here the assembly code for moneypunct ctor:
-------------
_EXPLICIT moneypunct (_RWSTD_SIZE_T __refs = 0)
: _RW::__rw_facet (__refs), money_base () { }
004018C0 push ebp
004018C1 mov ebp,esp
004018C3 push ecx
004018C4 mov dword ptr [ebp-4],ecx
004018C7 mov eax,dword ptr [__refs]
004018CA push eax
004018CB mov ecx,dword ptr [this]
004018CE call __rw::__rw_facet::__rw_facet (412E20h)
004018D3 xor ecx,ecx
004018D5 mov edx,dword ptr [this]
004018D8 add edx,38h // the sizeof
(moneypunct) == 0x38
004018DB mov byte ptr [edx],cl // here the place of
the buffer overrun
004018DD mov eax,dword ptr [this]
004018E0 mov dword ptr [eax],offset
std::moneypunct<char,0>::`vftable' (488838h)
004018E6 mov eax,dword ptr [this]
004018E9 mov esp,ebp
004018EB pop ebp
004018EC ret 4
-------------
When I commented the money_base () call the test succeeded and
assembly code has changed to:
-------------
_EXPLICIT moneypunct (_RWSTD_SIZE_T __refs = 0)
: _RW::__rw_facet (__refs)/*, money_base ()*/ { }
004018C0 push ebp
004018C1 mov ebp,esp
004018C3 push ecx
004018C4 mov dword ptr [ebp-4],ecx
004018C7 mov eax,dword ptr [__refs]
004018CA push eax
004018CB mov ecx,dword ptr [this]
004018CE call __rw::__rw_facet::__rw_facet (412E20h)
004018D3 mov ecx,dword ptr [this]
004018D6 mov dword ptr [ecx],offset
std::moneypunct<char,0>::`vftable' (488838h)
004018DC mov eax,dword ptr [this]
004018DF mov esp,ebp
004018E1 pop ebp
004018E2 ret 4
-------------
Here the same assembly, but in 12s configuration:
before change:
-------------
const PunctT pun;
004018B1 push 1
004018B3 lea ecx,[esp+0B4h]
004018BA call __rw::__rw_facet::__rw_facet (40A770h)
004018BF mov byte ptr [esp+0E8h],bl // 0xE8 - 0xB4
== 0x34, so here not buffer overrun,
// but maybe changed last 4-byte member of the __rw_facet
// (I suppose is _C_pid)
004018C6 mov dword ptr [esp+0B0h],offset
Punct<char,0>::`vftable' (43A258h)
-------------
after change:
-------------
const PunctT pun;
00401891 push 1
00401893 lea ecx,[esp+0B4h]
0040189A call __rw::__rw_facet::__rw_facet (40A720h)
0040189F mov dword ptr [esp+0B0h],offset
Punct<char,0>::`vftable' (43A258h)
-------------
The money_base is empty class with default ctor and I think we could
remove explicit invoking
of the money_base() from the moneypunct ctor initialization list.
I have not verified, but I suppose that the same problem might be with
messages class.
The patch is below:
ChangeLog:
* _messages.h (messages): Removed explicit invoking of the
messages_base() ctor
to avoid buffer overrun due to bad code generation on MSVC 7.1.
* _moneypunct.h (moneypunct): Removed explicit invoking of the
money_base() ctor
to avoid buffer overrun due to bad code generation on MSVC 7.1.
-------------
Index: loc/_messages.h
===================================================================
--- loc/_messages.h (revision 575203)
+++ loc/_messages.h (working copy)
@@ -82,7 +82,7 @@
allocator<char_type> > string_type;
_EXPLICIT messages (_RWSTD_SIZE_T __refs = 0)
- : _RW::__rw_facet (__refs), messages_base () { }
+ : _RW::__rw_facet (__refs) { }
catalog open (const string& __fun, const locale& __loc) const {
Index: loc/_moneypunct.h
===================================================================
--- loc/_moneypunct.h (revision 575203)
+++ loc/_moneypunct.h (working copy)
@@ -66,7 +66,7 @@
string_type;
_EXPLICIT moneypunct (_RWSTD_SIZE_T __refs = 0)
- : _RW::__rw_facet (__refs), money_base () { }
+ : _RW::__rw_facet (__refs) { }
char_type decimal_point () const {
return do_decimal_point ();
-------------
Farid.