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