B
Brian
I would have thought that C++ would not allow a jump (goto) to a place
before a local object was instantiated, but it works! The local object's
destructor is called and then it is REinstantiated. Is this just the
behavior of VC++? Please discuss why this needs to be allowed and why it
is or could be an exploitable feature. (Comments about use of 'goto' and
programming style are irrelevant and off-topic). Example code and
generated assembly below.
void Foo1()
{
label_before_a:
A a;
// The following goto causes endless loop of constructing then
destructing 'a'!
goto label_before_a;
}
void Foo2(bool repeat_flag)
{
label_before_a:
A a;
// The following goto causes endless loop if repeat_flag is set!
if(repeat_flag)
goto label_before_a;
// do something with 'a'.
}
Generated assembly for above functions:
// Foo1 ------------------------------------------------------
PUBLIC ?Foo1@@YGXXZ ; Foo1
; Function compile flags: /Odtp /RTCcu
; File e:\dev\prod\foundation\test\test.cpp
_TEXT SEGMENT
_a$ = -1 ; size = 1
?Foo1@@YGXXZ PROC ; Foo1
; 18 : {
push ebp
mov ebp, esp
push ecx
$label_before_a$15656:
; 19 : label_before_a:
; 20 : A a;
lea ecx, DWORD PTR _a$[ebp]
call ??0A@@QAE@XZ ; A::A
; 21 : // The following goto causes endless loop of constructing
then destructing 'a'!
; 22 : goto label_before_a;
lea ecx, DWORD PTR _a$[ebp]
call ??1A@@QAE@XZ ; A::~A
jmp SHORT $label_before_a$15656
; 23 : }
mov esp, ebp
pop ebp
ret 0
?Foo1@@YGXXZ ENDP ; Foo1
_TEXT ENDS
// Foo2 ------------------------------------------------------
PUBLIC ?Foo2@@YGXH@Z ; Foo2
; Function compile flags: /Odtp /RTCcu
_TEXT SEGMENT
_a$ = -1 ; size = 1
_repeat_flag$ = 8 ; size = 4
?Foo2@@YGXH@Z PROC ; Foo2
; 26 : {
push ebp
mov ebp, esp
push ecx
$label_before_a$15661:
; 27 : label_before_a:
; 28 : A a;
lea ecx, DWORD PTR _a$[ebp]
call ??0A@@QAE@XZ ; A::A
; 29 : // The following goto causes endless loop if repeat_flag is
set!
; 30 : if(repeat_flag)
cmp DWORD PTR _repeat_flag$[ebp], 0
je SHORT $LN1@Foo2
; 31 : goto label_before_a;
lea ecx, DWORD PTR _a$[ebp]
call ??1A@@QAE@XZ ; A::~A
jmp SHORT $label_before_a$15661
$LN1@Foo2:
; 32 : // do something with 'a'.
; 33 : }
lea ecx, DWORD PTR _a$[ebp]
call ??1A@@QAE@XZ ; A::~A
mov esp, ebp
pop ebp
ret 4
?Foo2@@YGXH@Z ENDP ; Foo2
_TEXT ENDS
before a local object was instantiated, but it works! The local object's
destructor is called and then it is REinstantiated. Is this just the
behavior of VC++? Please discuss why this needs to be allowed and why it
is or could be an exploitable feature. (Comments about use of 'goto' and
programming style are irrelevant and off-topic). Example code and
generated assembly below.
void Foo1()
{
label_before_a:
A a;
// The following goto causes endless loop of constructing then
destructing 'a'!
goto label_before_a;
}
void Foo2(bool repeat_flag)
{
label_before_a:
A a;
// The following goto causes endless loop if repeat_flag is set!
if(repeat_flag)
goto label_before_a;
// do something with 'a'.
}
Generated assembly for above functions:
// Foo1 ------------------------------------------------------
PUBLIC ?Foo1@@YGXXZ ; Foo1
; Function compile flags: /Odtp /RTCcu
; File e:\dev\prod\foundation\test\test.cpp
_TEXT SEGMENT
_a$ = -1 ; size = 1
?Foo1@@YGXXZ PROC ; Foo1
; 18 : {
push ebp
mov ebp, esp
push ecx
$label_before_a$15656:
; 19 : label_before_a:
; 20 : A a;
lea ecx, DWORD PTR _a$[ebp]
call ??0A@@QAE@XZ ; A::A
; 21 : // The following goto causes endless loop of constructing
then destructing 'a'!
; 22 : goto label_before_a;
lea ecx, DWORD PTR _a$[ebp]
call ??1A@@QAE@XZ ; A::~A
jmp SHORT $label_before_a$15656
; 23 : }
mov esp, ebp
pop ebp
ret 0
?Foo1@@YGXXZ ENDP ; Foo1
_TEXT ENDS
// Foo2 ------------------------------------------------------
PUBLIC ?Foo2@@YGXH@Z ; Foo2
; Function compile flags: /Odtp /RTCcu
_TEXT SEGMENT
_a$ = -1 ; size = 1
_repeat_flag$ = 8 ; size = 4
?Foo2@@YGXH@Z PROC ; Foo2
; 26 : {
push ebp
mov ebp, esp
push ecx
$label_before_a$15661:
; 27 : label_before_a:
; 28 : A a;
lea ecx, DWORD PTR _a$[ebp]
call ??0A@@QAE@XZ ; A::A
; 29 : // The following goto causes endless loop if repeat_flag is
set!
; 30 : if(repeat_flag)
cmp DWORD PTR _repeat_flag$[ebp], 0
je SHORT $LN1@Foo2
; 31 : goto label_before_a;
lea ecx, DWORD PTR _a$[ebp]
call ??1A@@QAE@XZ ; A::~A
jmp SHORT $label_before_a$15661
$LN1@Foo2:
; 32 : // do something with 'a'.
; 33 : }
lea ecx, DWORD PTR _a$[ebp]
call ??1A@@QAE@XZ ; A::~A
mov esp, ebp
pop ebp
ret 4
?Foo2@@YGXH@Z ENDP ; Foo2
_TEXT ENDS