C++ compiler generates code that reads beyond top of stack

Source: Microsoft Support

RAPID PUBLISHING

RAPID PUBLISHING ARTICLES PROVIDE INFORMATION DIRECTLY FROM WITHIN THE MICROSOFT SUPPORT ORGANIZATION. THE INFORMATION CONTAINED HEREIN IS CREATED IN RESPONSE TO EMERGING OR UNIQUE TOPICS, OR IS INTENDED SUPPLEMENT OTHER KNOWLEDGE BASE INFORMATION.

Symptom



Under certain conditions, the C++ compilers shipped with VS2005, VS2005SP1 and VS2008 generate code that reads from memory in the stack region but beyond the top of stack. This is incorrect and causes Rational Purify Plus to report a BSR (Beyond Stack Read) error when the program is run under Purify.

Here is some example C++ source code that demonstrates the problem




#define _SECURE_SCL (0)


#define _HAS_ITERATOR_DEBUGGING (0)


#include <vector>


void bug4 (const std::vector<double>& base, std::vector<double>& lossGrid, bool b)


{


long arr[100];


lossGrid.assign(base.begin(), base.end());


 


for (int i = 0; i < 100; ++i)


{


if (b)


{


arr[i] = 0;


}


}


}


Here is the start of the generated code, when compiled in a Release build with optimizations enabled (/O2), stack frame pointer omission enabled, link-time code generation off, and buffer security checking off:


_TEXT SEGMENT


$T15763 = -404 ; size = 1


_base$ = 8 ; size = 4


_lossGrid$ = 12 ; size = 4


_b$ = 16 ; size = 1


?bug4@@YAXABV?$vector@NV?$allocator@N@std@@@std@@AAV12@_N@Z PROC ; bug4, COMDAT


 


; 8 : long arr[100];


; 9 : lossGrid.assign(base.begin(), base.end());


 


00000 8b 44 24 04 mov eax, DWORD PTR _base$[esp-4]


00004 8b 48 08 mov ecx, DWORD PTR [eax+8]


00007 8b 94 24 6c fe


ff ff mov edx, DWORD PTR $T15763[esp]


0000e 8b 40 04 mov eax, DWORD PTR [eax+4]


00011 81 ec 94 01 00


00 sub esp, 404 ; 00000194H


00017 52 push edx


The "mov eax" instruction is reading from a negative address relative to the stack pointer, which is incorrect.


 

Resolution



Since there aren't any flags to disable shrink wrapping without turning off all optimizations, the best work around is to turn off frame pointer omission for that function. To do this you can wrap the offending function with


#pragma optimize("y", off)


// function or functions that exhibit bug here


#pragma optimize("", on)



The first pragma turns off Frame Pointer Omission (it's the same as having /Oy- for that function) and the second pragma restores the optimization options to the ones specified on the command line.

DISCLAIMER

MICROSOFT AND/OR ITS SUPPLIERS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY, RELIABILITY OR ACCURACY OF THE INFORMATION CONTAINED IN THE DOCUMENTS AND RELATED GRAPHICS PUBLISHED ON THIS WEBSITE (THE “MATERIALS”) FOR ANY PURPOSE. THE MATERIALS MAY INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS AND MAY BE REVISED AT ANY TIME WITHOUT NOTICE.


TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND/OR ITS SUPPLIERS DISCLAIM AND EXCLUDE ALL REPRESENTATIONS, WARRANTIES, AND CONDITIONS WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO REPRESENTATIONS, WARRANTIES, OR CONDITIONS OF TITLE, NON INFRINGEMENT, SATISFACTORY CONDITION OR QUALITY, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE MATERIALS.
Eigenschappen

Artikel-id: 969191 - Laatst bijgewerkt: 18 mrt. 2009 - Revisie: 1

Feedback