/home66/gary/public_html/cloudy/c08_branch/source/parse_crashdo.cpp

Go to the documentation of this file.
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 }

Generated on Mon Feb 16 12:01:25 2009 for cloudy by  doxygen 1.4.7