cloudy trunk
Loading...
Searching...
No Matches
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 */
32const int ARR_SIZE = 10;
33
34/* static variable used in undefined and bounds tests */
35static 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}
FILE * ioQQQ
Definition cddefines.cpp:7
float sys_float
Definition cddefines.h:106
#define isnan
Definition cddefines.h:620
#define ASSERT(exp)
Definition cddefines.h:578
#define MALLOC(exp)
Definition cddefines.h:501
const double ZeroNum
Definition cdinit.cpp:13
#define EXIT_FAILURE
Definition cddefines.h:140
#define cdEXIT(FAIL)
Definition cddefines.h:434
#define DEBUG_ENTRY(funcname)
Definition cddefines.h:684
double FFmtRead(void)
Definition parser.cpp:353
bool nMatch(const char *chKey) const
Definition parser.h:135
bool lgEOL(void) const
Definition parser.h:98
iterator ptr(size_type i1, size_type i2)
void reserve(size_type i1)
multi_arr< double, 2 >::iterator md2i
bool MyIsnan(const sys_float &x)
Definition cpu.cpp:753
void set_NaN(sys_float &x)
Definition cpu.cpp:682
static double ar2[ARR_SIZE]
void ParseCrashDo(Parser &p)
const int ARR_SIZE