cloudy  trunk
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parse_crashdo.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*ParseCrashDo any of several tests to check that the code can crash */
4 #include "cddefines.h"
5 #include "parse.h"
6 
7 #ifdef _MSC_VER
8  /* disable warning about undefined vars being used - one of the tests shall do exactly that */
9 # pragma warning( disable : 4700 )
10  /* disable warning about division by zero */
11 # pragma warning( disable : 4756 )
12  /* disable warning that conditional expression is constant, true or false in if */
13 # pragma warning( disable : 4127 )
14 #endif
15 
16 #ifdef __INTEL_COMPILER
17 # pragma warning( disable : 592 )
18 #endif
19 
20 /* this is size of array used in array bounds exceeded crash test */
21 const int ARR_SIZE = 10;
22 
23 /* static variable used in undefined and bounds tests */
24 static double ar2[ARR_SIZE];
25 
26 // force optimization off; any level of optimization will kill the
27 // functionality of this routine
28 #if defined(_MSC_VER) || defined(__ICC)
29 #pragma optimize("", off)
30 #elif defined(__PGI)
31 #pragma global opt=0
32 #elif defined(__HP_aCC)
33 #pragma OPT_LEVEL 0
34 #endif
35 
36 /*ParseCrashDo any of several tests to check that the code can crash */
37 void ParseCrashDo(char *chCard)
38 {
39  double ar1, br1;
40  long int i;
41  bool lgCrash = false;
42 
43  DEBUG_ENTRY( "ParseCrashDo()" );
44 
45  /* div by 0 to get crash as check on FP environment */
46  if( nMatch("ZERO",chCard) )
47  {
48  fprintf(ioQQQ," I will now div by 0 to get crash. Hold on.\n");
49  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
50  fflush(ioQQQ);
51  ar1 = 1. / ZeroNum;
52  fprintf(ioQQQ," I am still alive - something is wrong, result is %e\n",
53  ar1);
54  lgCrash = true;
55  }
56 
57  /* use some undefined numbers */
58  else if( nMatch("UNDE",chCard) )
59  {
60  if( nMatch("STAT",chCard) )
61  {
62  fprintf(ioQQQ," Now I will now use an undefined static variable. Hold on.\n");
63  fprintf(ioQQQ," This should never fail since the compiler should have automatically initialized it to zero.\n");
64  fflush(ioQQQ);
65  /*lint -e530 ar2 not initialized */
66  ar2[0] *= 1e-10;
67  /*lint +e530 ar2 not initialized */
68 
69  fprintf(ioQQQ," I am still alive, this is the expected result. The "
70  "result of the multiplication of undefined by 1e-10 is "
71  "%e\n", ar2[0] );
72  fflush(ioQQQ);
73  }
74  else if( nMatch("STAC",chCard) || nMatch("AUTO",chCard) )
75  {
76  double A_variable_which_SHOULD_be_used_uninitialized;
77  fprintf(ioQQQ," Now I will now use an undefined variable off the stack. Hold on.\n");
78  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
79  fflush(ioQQQ);
80  /*lint -e530 a not initialized */
81  A_variable_which_SHOULD_be_used_uninitialized *= 1e-10f;
82  /*lint +e530 a not initialized */
83 
84  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 );
85  fflush(ioQQQ);
86  }
87  else
88  {
89  double *aa = (double*)MALLOC(3*sizeof(double));
90  fprintf(ioQQQ," I will now use an undefined variable off the heap obtained with malloc. Hold on.\n");
91  /* MyIsnan is guaranteed not to crash on FPE */
92  if( MyIsnan( aa[1] ) )
93  fprintf(ioQQQ," The malloc'ed memory was set to NaN.\n" );
94  else
95  fprintf(ioQQQ," The malloc'ed memory was NOT initialized by MyMalloc.\n" );
96  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
97  fflush(ioQQQ);
98  /*lint -e530 aa[1] not initialized */
99  aa[1] *= 1e-10;
100  /*lint +e530 aa[1] not initialized */
101  fprintf(ioQQQ," I am still alive - something is wrong, the result of the multiplication of undefined by 1e-10 is %e\n", aa[1] );
102  fflush(ioQQQ);
103  free( aa );
104  }
105  lgCrash = true;
106  }
107 
108  /* make overflow to get crash as check on FP environment */
109  else if( nMatch("OVER",chCard) && nMatch("LONG",chCard) )
110  {
111  long lng;
112  fprintf(ioQQQ," I will now make long overflow to get crash. Hold on.\n");
113  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
114  fflush(ioQQQ);
115  lng = (long)(LONG_MAX*sqrt(1e6));
116  fprintf(ioQQQ," I am still alive - something is wrong, the result was %li\n",
117  lng);
118  lgCrash = true;
119  }
120 
121  /* make overflow to get crash as check on FP environment */
122  else if( nMatch("OVER",chCard) )
123  {
124  ar1 = 1e-20;
125  fprintf(ioQQQ," I will now make floating point overflow to get crash. Hold on.\n");
126  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
127  fflush(ioQQQ);
128  br1 = DBL_MAX / ar1;
129  fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n",
130  br1);
131  lgCrash = true;
132  }
133 
134  /* assert false test to get crash as check on environment */
135  else if( nMatch("ASSE",chCard) )
136  {
137  fprintf(ioQQQ," I will now assert that a false statement is true to get a crash.\n\n");
138  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");
139  fprintf(ioQQQ," If the next line says \"I am still alive - the assert macro is not working ....\" then there are problems.\n\n");
140  fflush(ioQQQ);
141  ASSERT( DBL_MAX < ZeroNum );
142  fprintf(ioQQQ," I am still alive - the assert macro is not working in this executable.\n");
143  lgCrash = true;
144  }
145 
146  /* assert ratios of zeros (NaN) to get crash as check on environment */
147  else if( nMatch(" NAN",chCard) )
148  {
149  ar1 = 0.;
150  fprintf(ioQQQ," I will now make invalid operation (div 0 by 0) to get crash. Hold on.\n");
151  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
152  fflush(ioQQQ);
153  br1 = ar1 / ZeroNum;
154  fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n",
155  br1);
156  lgCrash = true;
157  }
158 
159  /* assert that the set_NaN routine works properly for floats */
160  else if( nMatch("SETN",chCard) && nMatch("FLOA",chCard) )
161  {
162  sys_float f;
163  fprintf(ioQQQ," I will now initialize a float to a signaling NaN. This should never crash!\n");
164  set_NaN(f);
165  fprintf(ioQQQ," Initialization finished. I will now perform an operation on this variable. Hold on.\n");
166  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
167  fflush(ioQQQ);
168  f *= 2.f;
169  fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n",
170  f);
171  lgCrash = true;
172  }
173 
174  /* assert that the set_NaN routine works properly for doubles */
175  else if( nMatch("SETN",chCard) )
176  {
177  double d;
178  fprintf(ioQQQ," I will now initialize a double to a signaling NaN. This should never crash!\n");
179  set_NaN(d);
180  fprintf(ioQQQ," Initialization finished. I will now perform an operation on this variable. Hold on.\n");
181  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong ....\" then there are problems.\n");
182  fflush(ioQQQ);
183  d *= 2.;
184  fprintf(ioQQQ," I am still alive - something is wrong, the result was %e\n",
185  d);
186  lgCrash = true;
187  }
188 
189  /* test what happens with an array index out of bounds
190  * two options, low for [<0] and high for [>limit] */
191  else if( nMatch("BOUN",chCard) )
192  {
193  bool lgEOL;
194  double x;
195  i = 5;
196 
197  /* read offset */
198  x = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL);
199  if( lgEOL && nMatch(" LOW", chCard ) )
200  x = -2.;
201  if( lgEOL && nMatch("HIGH", chCard ) )
202  x = 2.;
203 
204  /* if x >= 0 (which includes default case where x is no entered)
205  * i will be x beyond the end of the array, or x before the start */
206  i = ( x >= 0. ) ? (long)(x+0.5) + ARR_SIZE : (long)(x-0.5);
207 
208  /* must turn off PCLint detection of logical errors in this block */
209  if( nMatch("STAT",chCard) )
210  {
211  fprintf(ioQQQ," I will now access static array element ar2[%ld]. Hold on.\n", i );
212  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n");
213  fflush(ioQQQ);
214  ar2[i] = 1e-10;
215 
216  fprintf(ioQQQ," I am still alive - something is wrong\n" );
217  fflush(ioQQQ);
218  }
219  else if( nMatch("STAC",chCard) || nMatch("AUTO",chCard) )
220  {
221  double a[ARR_SIZE];
222  fprintf(ioQQQ," I will now access automatic array element a[%ld]. Hold on.\n", i );
223  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n");
224  fflush(ioQQQ);
225  a[i] = 1e-10;
226 
227  fprintf(ioQQQ," I am still alive - something is wrong, return value was %.2e\n", a[i] );
228  fflush(ioQQQ);
229  }
230  else if( nMatch("HEAP",chCard) )
231  {
232  int *ibound;
233  ibound = ((int *)MALLOC( ARR_SIZE*sizeof(int) ));
234  fprintf(ioQQQ," I will now access malloced heap array element ibound[%ld]. Hold on.\n", i );
235  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n");
236  fflush(ioQQQ);
237  ibound[i] = 1;
238  fprintf(ioQQQ," I am still alive - something is wrong, return value is %i\n" , ibound[i] );
239  fflush(ioQQQ);
240  free(ibound);
241  }
242  else if( nMatch("MULT",chCard) )
243  {
244  /* this tests the multi_arr class testing which occurs if the
245  * macro BOUNDS_CHECK is set at compile time */
247  b.reserve(3);
248  for( int j=0; j < 3; j++ )
249  b.reserve(j,ARR_SIZE+j);
250  b.alloc();
251  if( nMatch("ITER",chCard) )
252  {
253  fprintf(ioQQQ," I will now access multi_arr array element *b.ptr(0,%ld). Hold on.\n", i );
254  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n\n");
255  fflush(ioQQQ);
256  md2i p = b.ptr(0,i);
257  *p = 2.;
258  fprintf(ioQQQ," I am still alive - something is wrong, return value is %g\n", *p );
259  fflush(ioQQQ);
260  }
261  else
262  {
263  fprintf(ioQQQ," I will now access multi_arr array element b[0][%ld]. Hold on.\n", i );
264  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n\n");
265  fflush(ioQQQ);
266  b[0][i] = 2.;
267  fprintf(ioQQQ," I am still alive - something is wrong, return value is %g\n" , b[0][i] );
268  fflush(ioQQQ);
269  }
270  b.clear();
271  }
272  else
273  {
274  fprintf(ioQQQ," The CRASH BOUNDS command has four different tests. One must be specified\n" );
275  fprintf(ioQQQ," The HEAP option tests a malloc/'d array - this tests valgrind or purify.\n");
276  fprintf(ioQQQ," The STATIC option tests a static declared array, and the STACK or AUTO option tests an automatic array - these test pgcc.\n");
277  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" );
278  fprintf(ioQQQ," All have a number as an optional argument, the array element to be accessed.\n");
279  fflush(ioQQQ);
280  }
281  lgCrash = true;
282  }
283 
284  /* test the isnan function */
285  else if( nMatch("ISNA",chCard) )
286  {
287  if( nMatch("FLOA",chCard) )
288  {
289  sys_float ff;
290  fprintf(ioQQQ," I will now set a float to SNaN. This should never crash!\n" );
291  set_NaN( ff );
292  fprintf(ioQQQ," I will now test this variable with the isnan function\n" );
293  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");
294  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n");
295  ASSERT( !isnan( ff ) );
296  fprintf(ioQQQ," I am still alive - something is wrong, value is %e\n", ff );
297  }
298  else
299  {
300  double dd;
301  fprintf(ioQQQ," I will now set a double to SNaN. This should never crash!\n" );
302  set_NaN( dd );
303  fprintf(ioQQQ," I will now test this variable with the isnan function\n" );
304  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");
305  fprintf(ioQQQ," If the next line says \"I am still alive - something is wrong\" then there are problems.\n");
306  ASSERT( !isnan( dd ) );
307  fprintf(ioQQQ," I am still alive - something is wrong, value is %e\n", dd );
308  }
309  }
310 
311  /* test if a C++ exception is caught */
312  else if( nMatch("EXCE",chCard) )
313  {
314  fprintf(ioQQQ," I will now throw a C++ exception of type out_of_range()\n" );
315  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");
316  fprintf(ioQQQ," If you get any other message, the exception was not caught correctly.\n\n");
317  throw out_of_range( "Cloudy Test" );
318  fprintf(ioQQQ," If you see this statement, the exception did not terminate the program.\n" );
319  }
320 
321  else
322  {
323  fprintf(ioQQQ,
324  "Crash option not found - valid options are ZERO, UNDEfined,"
325  " OVERflow, ASSErt, _NAN, SETNan, BOUNds, ISNAn, and EXCEption.\nSorry.\n");
326  lgCrash = true;
327  }
328 
329  if( lgCrash )
330  {
331  cdEXIT(EXIT_FAILURE);
332  }
333 }

Generated for cloudy by doxygen 1.8.1.2