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