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

  1. // options: /Oxs /EHa /GX
  2. #include "stdio.h"
  3. #include "windows.h"
  4. typedef void (*PEXCEPTION_TEST) (void (*p)(void), volatile int *State);
  5. typedef struct _EXCEPTION_TEST_INFO {
  6. PEXCEPTION_TEST ExceptionTest;
  7. int State;
  8. } EXCEPTION_TEST_INFO;
  9. void TestUnwindFromRecoveryCodeInFinally (void (*p)(void), volatile int *State);
  10. void TestUnwindFromRecoveryCodeTryFinallyBlock (void (*p)(void), volatile int *State);
  11. void TestUnwindFromRecoverCodeDuplicatesScopeEntries (void (*p)(void), volatile int *State);
  12. void TestUnwindFromInfiniteLoop (void (*p)(void), volatile int *State);
  13. void TestExtendedTrySCopeForRecoveryCode (void (*p)(void), volatile int *State);
  14. void TestIPStatesCoverRecoveryCode (void (*p)(void), volatile int *State);
  15. void TestNestedFinally (void (*p)(void), volatile int *State);
  16. EXCEPTION_TEST_INFO ExceptionTests[] = { {TestNestedFinally, 3 },
  17. {TestExtendedTrySCopeForRecoveryCode, 2},
  18. {TestIPStatesCoverRecoveryCode, 2},
  19. {TestUnwindFromInfiniteLoop, 2},
  20. {TestUnwindFromRecoverCodeDuplicatesScopeEntries, 4},
  21. {TestUnwindFromRecoveryCodeTryFinallyBlock, 1},
  22. {TestUnwindFromRecoveryCodeInFinally, 1},
  23. };
  24. const MaxExceptionTests = sizeof(ExceptionTests) / sizeof(EXCEPTION_TEST_INFO);
  25. //
  26. // Test that recovery code is covered by extended try scope.
  27. void TestExtendedTrySCopeForRecoveryCode (void (*p)(void), volatile int *State)
  28. {
  29. __try
  30. {
  31. if ((int)p != 1)
  32. {
  33. (*p)();
  34. }
  35. }
  36. __finally
  37. {
  38. ++*State++;
  39. }
  40. }
  41. // VSWhidbey:14611
  42. // Test that recovery code for finally block is covered by full pdata range.
  43. // Inspect code to be sure LD.S/CHK is generated in funclet for (*p).
  44. // Failure will cause bad unwind and program will fail.
  45. void TestUnwindFromRecoveryCodeInFinally (void (*p)(void), volatile int *State)
  46. {
  47. __try
  48. {
  49. // transfer to finally funclet
  50. (*p)();
  51. }
  52. __finally
  53. {
  54. // cause speculative load of p (ld.s p) and chk to fail. If recovery code isn't covered by pdata range of
  55. // funclet unwind will fail.
  56. if ((int)p != 1)
  57. {
  58. (*p)();
  59. }
  60. }
  61. }
  62. // VSWhidbey:10415
  63. // Test that if the extended scope table entry ends at the beginning address of finally funclet that
  64. // the runtime (CRT, RTL) doesn't use it's address as the NextPC after invoking the finally. This leads
  65. // to the finally being called twice and unwinding failing. This bug fixed in CRT and RTL.
  66. void TestUnwindFromRecoveryCodeTryFinallyBlock (void (*p)(void), volatile int *State)
  67. {
  68. int rg[5];
  69. rg[1] = 0; rg[2] = 0; rg[3] = 0;
  70. rg[3] = 0xC0000005;
  71. __try
  72. {
  73. if ((int)p != 1)
  74. {
  75. (*p)();
  76. }
  77. }
  78. __finally
  79. {
  80. RaiseException( rg[3], 0, 0, 0 );
  81. }
  82. }
  83. // VSWhidbey:10415
  84. // Test that nested scope table entries are duplicated for recover code.
  85. // Failure will cause finally to be called in wrong order
  86. void TestUnwindFromRecoverCodeDuplicatesScopeEntries (void (*p)(void), volatile int *State)
  87. {
  88. int rg[5];
  89. rg[1] = 0; rg[2] = 0; rg[3] = 0;
  90. __try
  91. {
  92. __try
  93. {
  94. rg[3] = 0xC0000005;
  95. if ((int)p != 1)
  96. {
  97. (*p)();
  98. }
  99. }
  100. __finally
  101. {
  102. ++*State;
  103. __try
  104. {
  105. RaiseException( rg[3], 0, 0, 0 );
  106. }
  107. __finally
  108. {
  109. ++*State;
  110. }
  111. }
  112. }
  113. __finally
  114. {
  115. ++*State;
  116. }
  117. }
  118. // VSWhidbeg:13074
  119. // Test that infinite loop covers the entire try/except body range.
  120. void TestUnwindFromInfiniteLoop (void (*p)(void), volatile int *State)
  121. {
  122. __try {
  123. if (!State)
  124. {
  125. ++*State;
  126. __leave;
  127. }
  128. while (1)
  129. {
  130. p();
  131. }
  132. }__except(1){
  133. ++*State;
  134. p();
  135. }
  136. }
  137. // VSWhidbey:15700 - Test Extended IP States cover Recovery Code
  138. void TestIPStatesCoverRecoveryCode (void (*p)(void), volatile int *State)
  139. {
  140. int rg[5];
  141. rg[1] = 0; rg[2] = 0; rg[3] = 0;
  142. try
  143. {
  144. try
  145. {
  146. rg[3] = 0xC0000005;
  147. if ((int)p != 1)
  148. {
  149. (*p)();
  150. }
  151. }
  152. catch (...)
  153. {
  154. ++*State;
  155. throw;
  156. }
  157. }
  158. catch (...)
  159. {
  160. ++*State;
  161. }
  162. }
  163. // VSWhidbey:14606
  164. void TestNestedFinally (void (*p)(void), volatile int *State)
  165. {
  166. // __try {
  167. __try {
  168. *State += *State / *State;
  169. } __finally {
  170. if (_abnormal_termination())
  171. ++*State;
  172. __try {
  173. // This thing is screwed up - IA64 is wrong, the AMD64 compiler chokes, x86's helper routine is just messed up.
  174. if (_abnormal_termination())
  175. ++*State;
  176. } __finally
  177. {
  178. if (_abnormal_termination()) // On x86 only, this is true, if the outer one is true, or if this on is true
  179. ++*State;
  180. }
  181. }
  182. // } __except(1){}
  183. }
  184. void main (void)
  185. {
  186. int i = 0;
  187. volatile int State = 0;
  188. printf("Number of tests = %d\n",MaxExceptionTests);
  189. for (i = 0; i < MaxExceptionTests; i++)
  190. {
  191. __try
  192. {
  193. State = 0;
  194. ExceptionTests[i].ExceptionTest(0, &State);
  195. }
  196. __except( 1 )
  197. {
  198. ++State;
  199. }
  200. if (ExceptionTests[i].State == State)
  201. printf("#%d pass\n", i+1);
  202. else
  203. printf("#%d fail, State == %d\n", i+1, State);
  204. }
  205. }