Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

324 lines
5.9 KiB

// options: /Oxs /EHa /GX
#include "stdio.h"
#include "windows.h"
typedef void (*PEXCEPTION_TEST) (void (*p)(void), volatile int *State);
typedef struct _EXCEPTION_TEST_INFO {
PEXCEPTION_TEST ExceptionTest;
int State;
} EXCEPTION_TEST_INFO;
void TestUnwindFromRecoveryCodeInFinally (void (*p)(void), volatile int *State);
void TestUnwindFromRecoveryCodeTryFinallyBlock (void (*p)(void), volatile int *State);
void TestUnwindFromRecoverCodeDuplicatesScopeEntries (void (*p)(void), volatile int *State);
void TestUnwindFromInfiniteLoop (void (*p)(void), volatile int *State);
void TestExtendedTrySCopeForRecoveryCode (void (*p)(void), volatile int *State);
void TestIPStatesCoverRecoveryCode (void (*p)(void), volatile int *State);
void TestNestedFinally (void (*p)(void), volatile int *State);
EXCEPTION_TEST_INFO ExceptionTests[] = { {TestNestedFinally, 3 },
{TestExtendedTrySCopeForRecoveryCode, 2},
{TestIPStatesCoverRecoveryCode, 2},
{TestUnwindFromInfiniteLoop, 2},
{TestUnwindFromRecoverCodeDuplicatesScopeEntries, 4},
{TestUnwindFromRecoveryCodeTryFinallyBlock, 1},
{TestUnwindFromRecoveryCodeInFinally, 1},
};
const MaxExceptionTests = sizeof(ExceptionTests) / sizeof(EXCEPTION_TEST_INFO);
//
// Test that recovery code is covered by extended try scope.
void TestExtendedTrySCopeForRecoveryCode (void (*p)(void), volatile int *State)
{
__try
{
if ((int)p != 1)
{
(*p)();
}
}
__finally
{
++*State++;
}
}
// VSWhidbey:14611
// Test that recovery code for finally block is covered by full pdata range.
// Inspect code to be sure LD.S/CHK is generated in funclet for (*p).
// Failure will cause bad unwind and program will fail.
void TestUnwindFromRecoveryCodeInFinally (void (*p)(void), volatile int *State)
{
__try
{
// transfer to finally funclet
(*p)();
}
__finally
{
// cause speculative load of p (ld.s p) and chk to fail. If recovery code isn't covered by pdata range of
// funclet unwind will fail.
if ((int)p != 1)
{
(*p)();
}
}
}
// VSWhidbey:10415
// Test that if the extended scope table entry ends at the beginning address of finally funclet that
// the runtime (CRT, RTL) doesn't use it's address as the NextPC after invoking the finally. This leads
// to the finally being called twice and unwinding failing. This bug fixed in CRT and RTL.
void TestUnwindFromRecoveryCodeTryFinallyBlock (void (*p)(void), volatile int *State)
{
int rg[5];
rg[1] = 0; rg[2] = 0; rg[3] = 0;
rg[3] = 0xC0000005;
__try
{
if ((int)p != 1)
{
(*p)();
}
}
__finally
{
RaiseException( rg[3], 0, 0, 0 );
}
}
// VSWhidbey:10415
// Test that nested scope table entries are duplicated for recover code.
// Failure will cause finally to be called in wrong order
void TestUnwindFromRecoverCodeDuplicatesScopeEntries (void (*p)(void), volatile int *State)
{
int rg[5];
rg[1] = 0; rg[2] = 0; rg[3] = 0;
__try
{
__try
{
rg[3] = 0xC0000005;
if ((int)p != 1)
{
(*p)();
}
}
__finally
{
++*State;
__try
{
RaiseException( rg[3], 0, 0, 0 );
}
__finally
{
++*State;
}
}
}
__finally
{
++*State;
}
}
// VSWhidbeg:13074
// Test that infinite loop covers the entire try/except body range.
void TestUnwindFromInfiniteLoop (void (*p)(void), volatile int *State)
{
__try {
if (!State)
{
++*State;
__leave;
}
while (1)
{
p();
}
}__except(1){
++*State;
p();
}
}
// VSWhidbey:15700 - Test Extended IP States cover Recovery Code
void TestIPStatesCoverRecoveryCode (void (*p)(void), volatile int *State)
{
int rg[5];
rg[1] = 0; rg[2] = 0; rg[3] = 0;
try
{
try
{
rg[3] = 0xC0000005;
if ((int)p != 1)
{
(*p)();
}
}
catch (...)
{
++*State;
throw;
}
}
catch (...)
{
++*State;
}
}
// VSWhidbey:14606
void TestNestedFinally (void (*p)(void), volatile int *State)
{
// __try {
__try {
*State += *State / *State;
} __finally {
if (_abnormal_termination())
++*State;
__try {
// This thing is screwed up - IA64 is wrong, the AMD64 compiler chokes, x86's helper routine is just messed up.
if (_abnormal_termination())
++*State;
} __finally
{
if (_abnormal_termination()) // On x86 only, this is true, if the outer one is true, or if this on is true
++*State;
}
}
// } __except(1){}
}
void main (void)
{
int i = 0;
volatile int State = 0;
printf("Number of tests = %d\n",MaxExceptionTests);
for (i = 0; i < MaxExceptionTests; i++)
{
__try
{
State = 0;
ExceptionTests[i].ExceptionTest(0, &State);
}
__except( 1 )
{
++State;
}
if (ExceptionTests[i].State == State)
printf("#%d pass\n", i+1);
else
printf("#%d fail, State == %d\n", i+1, State);
}
}