cloudy trunk
|
00001 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and 00002 * others. For conditions of distribution and use see copyright notice in license.txt */ 00003 /*ParseCrashDo any of several tests to check that the code can crash */ 00004 #include "cddefines.h" 00005 #include "parse.h" 00006 00007 #ifdef _MSC_VER 00008 /* disable warning about undefined vars being used - one of the tests shall do exactly that */ 00009 # pragma warning( disable : 4700 ) 00010 /* disable warning about division by zero */ 00011 # pragma warning( disable : 4756 ) 00012 /* disable warning that conditional expression is constant, true or false in if */ 00013 # pragma warning( disable : 4127 ) 00014 #endif 00015 00016 #ifdef __INTEL_COMPILER 00017 # pragma warning( disable : 592 ) 00018 #endif 00019 00020 /* this is size of array used in array bounds exceeded crash test */ 00021 const int ARR_SIZE = 10; 00022 00023 /* static variable used in undefined and bounds tests */ 00024 static double ar2[ARR_SIZE]; 00025 00026 // force optimization off; any level of optimization will kill the 00027 // functionality of this routine 00028 #if defined(_MSC_VER) || defined(__ICC) 00029 #pragma optimize("", off) 00030 #elif defined(__PGI) 00031 #pragma global opt=0 00032 #elif defined(__HP_aCC) 00033 #pragma OPT_LEVEL 0 00034 #endif 00035 00036 /*ParseCrashDo any of several tests to check that the code can crash */ 00037 void ParseCrashDo(char *chCard) 00038 { 00039 double ar1, br1; 00040 long int i; 00041 bool lgCrash = false; 00042 00043 DEBUG_ENTRY( "ParseCrashDo()" ); 00044 00045 /* div by 0 to get crash as check on FP environment */ 00046 if( nMatch("ZERO",chCard) ) 00047 { 00048 fprintf(ioQQQ," I will now div by 0 to get crash. Hold on.\n"); 00049 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00050 fflush(ioQQQ); 00051 ar1 = 1. / ZeroNum; 00052 fprintf(ioQQQ," I am still alive - something is wrong, result is %e\n", 00053 ar1); 00054 lgCrash = true; 00055 } 00056 00057 /* use some undefined numbers */ 00058 else if( nMatch("UNDE",chCard) ) 00059 { 00060 if( nMatch("STAT",chCard) ) 00061 { 00062 fprintf(ioQQQ," Now I will now use an undefined static variable. Hold on.\n"); 00063 fprintf(ioQQQ," This should never fail since the compiler should have automatically initialized it to zero.\n"); 00064 fflush(ioQQQ); 00065 /*lint -e530 ar2 not initialized */ 00066 ar2[0] *= 1e-10; 00067 /*lint +e530 ar2 not initialized */ 00068 00069 fprintf(ioQQQ," I am still alive, this is the expected result. The " 00070 "result of the multiplication of undefined by 1e-10 is " 00071 "%e\n", ar2[0] ); 00072 fflush(ioQQQ); 00073 } 00074 else if( nMatch("STAC",chCard) || nMatch("AUTO",chCard) ) 00075 { 00076 double A_variable_which_SHOULD_be_used_uninitialized; 00077 fprintf(ioQQQ," Now I will now use an undefined variable off the stack. Hold on.\n"); 00078 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00079 fflush(ioQQQ); 00080 /*lint -e530 a not initialized */ 00081 A_variable_which_SHOULD_be_used_uninitialized *= 1e-10f; 00082 /*lint +e530 a not initialized */ 00083 00084 fprintf(ioQQQ," I am still alive - something is wrong, the result of the multiplication of undefined by 1e-10 is %e\n", A_variable_which_SHOULD_be_used_uninitialized ); 00085 fflush(ioQQQ); 00086 } 00087 else 00088 { 00089 double *aa = (double*)MALLOC(3*sizeof(double)); 00090 fprintf(ioQQQ," I will now use an undefined variable off the heap obtained with malloc. Hold on.\n"); 00091 /* MyIsnan is guaranteed not to crash on FPE */ 00092 if( MyIsnan( aa[1] ) ) 00093 fprintf(ioQQQ," The malloc'ed memory was set to NaN.\n" ); 00094 else 00095 fprintf(ioQQQ," The malloc'ed memory was NOT initialized by MyMalloc.\n" ); 00096 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00097 fflush(ioQQQ); 00098 /*lint -e530 aa[1] not initialized */ 00099 aa[1] *= 1e-10; 00100 /*lint +e530 aa[1] not initialized */ 00101 fprintf(ioQQQ," I am still alive - something is wrong, the result of the multiplication of undefined by 1e-10 is %e\n", aa[1] ); 00102 fflush(ioQQQ); 00103 free( aa ); 00104 } 00105 lgCrash = true; 00106 } 00107 00108 /* make overflow to get crash as check on FP environment */ 00109 else if( nMatch("OVER",chCard) && nMatch("LONG",chCard) ) 00110 { 00111 long lng; 00112 fprintf(ioQQQ," I will now make long overflow to get crash. Hold on.\n"); 00113 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00114 fflush(ioQQQ); 00115 lng = (long)(LONG_MAX*sqrt(1e6)); 00116 fprintf(ioQQQ," I am still alive - something is wrong, the result was %li\n", 00117 lng); 00118 lgCrash = true; 00119 } 00120 00121 /* make overflow to get crash as check on FP environment */ 00122 else if( nMatch("OVER",chCard) ) 00123 { 00124 ar1 = 1e-20; 00125 fprintf(ioQQQ," I will now make floating point overflow to get crash. Hold on.\n"); 00126 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00127 fflush(ioQQQ); 00128 br1 = DBL_MAX / ar1; 00129 fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n", 00130 br1); 00131 lgCrash = true; 00132 } 00133 00134 /* assert false test to get crash as check on environment */ 00135 else if( nMatch("ASSE",chCard) ) 00136 { 00137 fprintf(ioQQQ," I will now assert that a false statement is true to get a crash.\n\n"); 00138 fprintf(ioQQQ," The correct behavior is for the statement \"PROBLEM DISASTER An assert has been thrown, this is bad\" to be printed, followed by lots more scary looking messages.\n\n"); 00139 fprintf(ioQQQ," If the next line says \"I am still alive - the assert macro is not working ....\" then there are problems.\n\n"); 00140 fflush(ioQQQ); 00141 ASSERT( DBL_MAX < ZeroNum ); 00142 fprintf(ioQQQ," I am still alive - the assert macro is not working in this executable.\n"); 00143 lgCrash = true; 00144 } 00145 00146 /* assert ratios of zeros (NaN) to get crash as check on environment */ 00147 else if( nMatch(" NAN",chCard) ) 00148 { 00149 ar1 = 0.; 00150 fprintf(ioQQQ," I will now make invalid operation (div 0 by 0) to get crash. Hold on.\n"); 00151 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00152 fflush(ioQQQ); 00153 br1 = ar1 / ZeroNum; 00154 fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n", 00155 br1); 00156 lgCrash = true; 00157 } 00158 00159 /* assert that the set_NaN routine works properly for floats */ 00160 else if( nMatch("SETN",chCard) && nMatch("FLOA",chCard) ) 00161 { 00162 sys_float f; 00163 fprintf(ioQQQ," I will now initialize a float to a signaling NaN. This should never crash!\n"); 00164 set_NaN(f); 00165 fprintf(ioQQQ," Initialization finished. I will now perform an operation on this variable. Hold on.\n"); 00166 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00167 fflush(ioQQQ); 00168 f *= 2.f; 00169 fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n", 00170 f); 00171 lgCrash = true; 00172 } 00173 00174 /* assert that the set_NaN routine works properly for doubles */ 00175 else if( nMatch("SETN",chCard) ) 00176 { 00177 double d; 00178 fprintf(ioQQQ," I will now initialize a double to a signaling NaN. This should never crash!\n"); 00179 set_NaN(d); 00180 fprintf(ioQQQ," Initialization finished. I will now perform an operation on this variable. Hold on.\n"); 00181 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n"); 00182 fflush(ioQQQ); 00183 d *= 2.; 00184 fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n", 00185 d); 00186 lgCrash = true; 00187 } 00188 00189 /* test what happens with an array index out of bounds 00190 * two options, low for [<0] and high for [>limit] */ 00191 else if( nMatch("BOUN",chCard) ) 00192 { 00193 bool lgEOL; 00194 double x; 00195 i = 5; 00196 00197 /* read offset */ 00198 x = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00199 if( lgEOL && nMatch(" LOW", chCard ) ) 00200 x = -2.; 00201 if( lgEOL && nMatch("HIGH", chCard ) ) 00202 x = 2.; 00203 00204 /* if x >= 0 (which includes default case where x is no entered) 00205 * i will be x beyond the end of the array, or x before the start */ 00206 i = ( x >= 0. ) ? (long)(x+0.5) + ARR_SIZE : (long)(x-0.5); 00207 00208 /* must turn off PCLint detection of logical errors in this block */ 00209 if( nMatch("STAT",chCard) ) 00210 { 00211 fprintf(ioQQQ," I will now access static array element ar2[%ld]. Hold on.\n", i ); 00212 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n"); 00213 fflush(ioQQQ); 00214 ar2[i] = 1e-10; 00215 00216 fprintf(ioQQQ," I am still alive - something is wrong\n" ); 00217 fflush(ioQQQ); 00218 } 00219 else if( nMatch("STAC",chCard) || nMatch("AUTO",chCard) ) 00220 { 00221 double a[ARR_SIZE]; 00222 fprintf(ioQQQ," I will now access automatic array element a[%ld]. Hold on.\n", i ); 00223 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n"); 00224 fflush(ioQQQ); 00225 a[i] = 1e-10; 00226 00227 fprintf(ioQQQ," I am still alive - something is wrong, return value was %.2e\n", a[i] ); 00228 fflush(ioQQQ); 00229 } 00230 else if( nMatch("HEAP",chCard) ) 00231 { 00232 int *ibound; 00233 ibound = ((int *)MALLOC( ARR_SIZE*sizeof(int) )); 00234 fprintf(ioQQQ," I will now access malloced heap array element ibound[%ld]. Hold on.\n", i ); 00235 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n"); 00236 fflush(ioQQQ); 00237 ibound[i] = 1; 00238 fprintf(ioQQQ," I am still alive - something is wrong, return value is %i\n" , ibound[i] ); 00239 fflush(ioQQQ); 00240 free(ibound); 00241 } 00242 else if( nMatch("MULT",chCard) ) 00243 { 00244 /* this tests the multi_arr class testing which occurs if the 00245 * macro BOUNDS_CHECK is set at compile time */ 00246 multi_arr<double,2> b; 00247 b.reserve(3); 00248 for( int j=0; j < 3; j++ ) 00249 b.reserve(j,ARR_SIZE+j); 00250 b.alloc(); 00251 if( nMatch("ITER",chCard) ) 00252 { 00253 fprintf(ioQQQ," I will now access multi_arr array element *b.ptr(0,%ld). Hold on.\n", i ); 00254 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n\n"); 00255 fflush(ioQQQ); 00256 md2i p = b.ptr(0,i); 00257 *p = 2.; 00258 fprintf(ioQQQ," I am still alive - something is wrong, return value is %g\n", *p ); 00259 fflush(ioQQQ); 00260 } 00261 else 00262 { 00263 fprintf(ioQQQ," I will now access multi_arr array element b[0][%ld]. Hold on.\n", i ); 00264 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n\n"); 00265 fflush(ioQQQ); 00266 b[0][i] = 2.; 00267 fprintf(ioQQQ," I am still alive - something is wrong, return value is %g\n" , b[0][i] ); 00268 fflush(ioQQQ); 00269 } 00270 b.clear(); 00271 } 00272 else 00273 { 00274 fprintf(ioQQQ," The CRASH BOUNDS command has four different tests. One must be specified\n" ); 00275 fprintf(ioQQQ," The HEAP option tests a malloc/'d array - this tests valgrind or purify.\n"); 00276 fprintf(ioQQQ," The STATIC option tests a static declared array, and the STACK or AUTO option tests an automatic array - these test pgcc.\n"); 00277 fprintf(ioQQQ," The MULTI option tests if bounds checking is enabled in the multi_arr class (i.e., if the preprocessor macro BOUNDS_CHECK has been set).\n" ); 00278 fprintf(ioQQQ," All have a number as an optional argument, the array element to be accessed.\n"); 00279 fflush(ioQQQ); 00280 } 00281 lgCrash = true; 00282 } 00283 00284 /* test the isnan function */ 00285 else if( nMatch("ISNA",chCard) ) 00286 { 00287 if( nMatch("FLOA",chCard) ) 00288 { 00289 sys_float ff; 00290 fprintf(ioQQQ," I will now set a float to SNaN. This should never crash!\n" ); 00291 set_NaN( ff ); 00292 fprintf(ioQQQ," I will now test this variable with the isnan function\n" ); 00293 fprintf(ioQQQ," The correct behavior is for the statement \"PROBLEM DISASTER An assert has been thrown, this is bad\" to be printed, followed by lots more scary looking messages.\n\n"); 00294 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n"); 00295 ASSERT( !isnan( ff ) ); 00296 fprintf(ioQQQ," I am still alive - something is wrong, value is %e\n", ff ); 00297 } 00298 else 00299 { 00300 double dd; 00301 fprintf(ioQQQ," I will now set a double to SNaN. This should never crash!\n" ); 00302 set_NaN( dd ); 00303 fprintf(ioQQQ," I will now test this variable with the isnan function\n" ); 00304 fprintf(ioQQQ," The correct behavior is for the statement \"PROBLEM DISASTER An assert has been thrown, this is bad\" to be printed, followed by lots more scary looking messages.\n\n"); 00305 fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n"); 00306 ASSERT( !isnan( dd ) ); 00307 fprintf(ioQQQ," I am still alive - something is wrong, value is %e\n", dd ); 00308 } 00309 } 00310 00311 /* test if a C++ exception is caught */ 00312 else if( nMatch("EXCE",chCard) ) 00313 { 00314 fprintf(ioQQQ," I will now throw a C++ exception of type out_of_range()\n" ); 00315 fprintf(ioQQQ," The correct behavior is for the statement \"DISASTER - An out_of_range exception was caught, what() = Cloudy Test. Bailing out...\" to be printed.\n\n"); 00316 fprintf(ioQQQ," If you get any other message, the exception was not caught correctly.\n\n"); 00317 throw out_of_range( "Cloudy Test" ); 00318 fprintf(ioQQQ," If you see this statement, the exception did not terminate the program.\n" ); 00319 } 00320 00321 else 00322 { 00323 fprintf(ioQQQ, 00324 "Crash option not found - valid options are ZERO, UNDEfined," 00325 " OVERflow, ASSErt, _NAN, SETNan, BOUNds, ISNAn, and EXCEption.\nSorry.\n"); 00326 lgCrash = true; 00327 } 00328 00329 if( lgCrash ) 00330 { 00331 cdEXIT(EXIT_FAILURE); 00332 } 00333 }