Wireshark
2.9.0-477-g68ec514b
The Wireshark network protocol analyzer
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
epan
exceptions.h
1
/* exceptions.h
2
* Wireshark's exceptions.
3
*
4
* Wireshark - Network traffic analyzer
5
* By Gerald Combs <gerald@wireshark.org>
6
* Copyright 1998 Gerald Combs
7
*
8
* SPDX-License-Identifier: GPL-2.0-or-later
9
*/
10
11
#ifndef __EXCEPTIONS_H__
12
#define __EXCEPTIONS_H__
13
14
#include "
except.h
"
15
16
/* Wireshark has only one exception group, to make these macros simple */
17
#define XCEPT_GROUP_WIRESHARK 1
18
26
#define BoundsError 1
27
39
#define ContainedBoundsError 2
40
48
#define ReportedBoundsError 3
49
54
#define FragmentBoundsError 4
55
59
#define TypeError 5
60
70
#define DissectorError 6
71
81
#define ScsiBoundsError 7
82
87
#define OutOfMemoryError 8
88
96
#define ReassemblyError 9
97
98
/*
99
* Catch errors that, if you're calling a subdissector and catching
100
* exceptions from the subdissector, and possibly dissecting more
101
* stuff after the subdissector returns or fails, mean it makes
102
* sense to continue dissecting:
103
*
104
* BoundsError indicates a configuration problem (the capture was
105
* set up to throw away data, and it did); there's no point in
106
* trying to dissect any more data, as there's no more data to dissect.
107
*
108
* FragmentBoundsError indicates a configuration problem (reassembly
109
* wasn't enabled or couldn't be done); there's no point in trying
110
* to dissect any more data, as there's no more data to dissect.
111
*
112
* OutOfMemoryError indicates what its name suggests; there's no point
113
* in trying to dissect any more data, as you're probably not going to
114
* have any more memory to use when dissecting them.
115
*
116
* Other errors indicate that there's some sort of problem with
117
* the packet; you should continue dissecting data, as it might
118
* be OK, and, even if it's not, you should report its problem
119
* separately.
120
*/
121
#define CATCH_NONFATAL_ERRORS \
122
CATCH4(ReportedBoundsError, ContainedBoundsError, ScsiBoundsError, ReassemblyError)
123
124
/*
125
* Catch all bounds-checking errors.
126
*/
127
#define CATCH_BOUNDS_ERRORS \
128
CATCH5(BoundsError, FragmentBoundsError, ReportedBoundsError, \
129
ContainedBoundsError, ScsiBoundsError)
130
131
/*
132
* Catch all bounds-checking errors, and catch dissector bugs.
133
* Should only be used at the top level, so that dissector bugs
134
* go all the way to the top level and get reported immediately.
135
*/
136
#define CATCH_BOUNDS_AND_DISSECTOR_ERRORS \
137
CATCH7(BoundsError, FragmentBoundsError, ContainedBoundsError, \
138
ReportedBoundsError, ScsiBoundsError, DissectorError, \
139
ReassemblyError)
140
141
/* Usage:
142
*
143
* TRY {
144
* code;
145
* }
146
*
147
* CATCH(exception) {
148
* code;
149
* }
150
*
151
* CATCH2(exception1, exception2) {
152
* code;
153
* }
154
*
155
* CATCH3(exception1, exception2, exception3) {
156
* code;
157
* }
158
*
159
* CATCH4(exception1, exception2, exception3, exception4) {
160
* code;
161
* }
162
*
163
* CATCH5(exception1, exception2, exception3, exception4, exception5) {
164
* code;
165
* }
166
*
167
* CATCH6(exception1, exception2, exception3, exception4, exception5, exception6) {
168
* code;
169
* }
170
*
171
* CATCH7(exception1, exception2, exception3, exception4, exception5, exception6, exception7) {
172
* code;
173
* }
174
*
175
* CATCH_NONFATAL_ERRORS {
176
* code;
177
* }
178
*
179
* CATCH_BOUNDS_ERRORS {
180
* code;
181
* }
182
*
183
* CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
184
* code;
185
* }
186
*
187
* CATCH_ALL {
188
* code;
189
* }
190
*
191
* FINALLY {
192
* code;
193
* }
194
*
195
* ENDTRY;
196
*
197
* ********* Never use 'goto' or 'return' inside the TRY, CATCH*, or
198
* ********* FINALLY blocks. Execution must proceed through ENDTRY before
199
* ********* branching out.
200
*
201
* This is really something like:
202
*
203
* {
204
* caught = FALSE:
205
* x = setjmp();
206
* if (x == 0) {
207
* <TRY code>
208
* }
209
* if (!caught && x == 1) {
210
* caught = TRUE;
211
* <CATCH(1) code>
212
* }
213
* if (!caught && x == 2) {
214
* caught = TRUE;
215
* <CATCH(2) code>
216
* }
217
* if (!caught && (x == 3 || x == 4)) {
218
* caught = TRUE;
219
* <CATCH2(3,4) code>
220
* }
221
* if (!caught && (x == 5 || x == 6 || x == 7)) {
222
* caught = TRUE;
223
* <CATCH3(5,6,7) code>
224
* }
225
* if (!caught && x != 0) {
226
* caught = TRUE;
227
* <CATCH_ALL code>
228
* }
229
* <FINALLY code>
230
* if(!caught) {
231
* RETHROW(x)
232
* }
233
* }<ENDTRY tag>
234
*
235
* All CATCH's must precede a CATCH_ALL.
236
* FINALLY must occur after any CATCH or CATCH_ALL.
237
* ENDTRY marks the end of the TRY code.
238
* TRY and ENDTRY are the mandatory parts of a TRY block.
239
* CATCH, CATCH_ALL, and FINALLY are all optional (although
240
* you'll probably use at least one, otherwise why "TRY"?)
241
*
242
* GET_MESSAGE returns string ptr to exception message
243
* when exception is thrown via THROW_MESSAGE()
244
*
245
* To throw/raise an exception.
246
*
247
* THROW(exception)
248
* RETHROW rethrow the caught exception
249
*
250
* A cleanup callback is a function called in case an exception occurs
251
* and is not caught. It should be used to free any dynamically-allocated data.
252
* A pop or call_and_pop should occur at the same statement-nesting level
253
* as the push.
254
*
255
* CLEANUP_CB_PUSH(func, data)
256
* CLEANUP_CB_POP
257
* CLEANUP_CB_CALL_AND_POP
258
*/
259
260
/* we do up to three passes through the bit of code after except_try_push(),
261
* and except_state is used to keep track of where we are.
262
*/
263
#define EXCEPT_CAUGHT 1
/* exception has been caught, no need to rethrow at
264
* ENDTRY */
265
266
#define EXCEPT_RETHROWN 2
/* the exception was rethrown from a CATCH
267
* block. Don't reenter the CATCH blocks, but do
268
* execute FINALLY and rethrow at ENDTRY */
269
270
#define EXCEPT_FINALLY 4
/* we've entered the FINALLY block - don't allow
271
* RETHROW, and don't reenter FINALLY if a
272
* different exception is thrown */
273
274
#define TRY \
275
{\
276
except_t *volatile exc; \
277
volatile int except_state = 0; \
278
static const except_id_t catch_spec[] = { \
279
{ XCEPT_GROUP_WIRESHARK, XCEPT_CODE_ANY } }; \
280
except_try_push(catch_spec, 1, &exc); \
281
\
282
if(except_state & EXCEPT_CAUGHT) \
283
except_state |= EXCEPT_RETHROWN; \
284
except_state &= ~EXCEPT_CAUGHT; \
285
\
286
if (except_state == 0 && exc == 0) \
287
/* user's code goes here */
288
289
#define ENDTRY \
290
/* rethrow the exception if necessary */
\
291
if(!(except_state&EXCEPT_CAUGHT) && exc != 0) \
292
except_rethrow(exc); \
293
except_try_pop();\
294
}
295
296
/* the (except_state |= EXCEPT_CAUGHT) in the below is a way of setting
297
* except_state before the user's code, without disrupting the user's code if
298
* it's a one-liner.
299
*/
300
#define CATCH(x) \
301
if (except_state == 0 && exc != 0 && \
302
exc->except_id.except_code == (x) && \
303
(except_state |= EXCEPT_CAUGHT)) \
304
/* user's code goes here */
305
306
#define CATCH2(x,y) \
307
if (except_state == 0 && exc != 0 && \
308
(exc->except_id.except_code == (x) || \
309
exc->except_id.except_code == (y)) && \
310
(except_state|=EXCEPT_CAUGHT)) \
311
/* user's code goes here */
312
313
#define CATCH3(x,y,z) \
314
if (except_state == 0 && exc != 0 && \
315
(exc->except_id.except_code == (x) || \
316
exc->except_id.except_code == (y) || \
317
exc->except_id.except_code == (z)) && \
318
(except_state|=EXCEPT_CAUGHT)) \
319
/* user's code goes here */
320
321
#define CATCH4(w,x,y,z) \
322
if (except_state == 0 && exc != 0 && \
323
(exc->except_id.except_code == (w) || \
324
exc->except_id.except_code == (x) || \
325
exc->except_id.except_code == (y) || \
326
exc->except_id.except_code == (z)) && \
327
(except_state|=EXCEPT_CAUGHT)) \
328
/* user's code goes here */
329
330
#define CATCH5(v,w,x,y,z) \
331
if (except_state == 0 && exc != 0 && \
332
(exc->except_id.except_code == (v) || \
333
exc->except_id.except_code == (w) || \
334
exc->except_id.except_code == (x) || \
335
exc->except_id.except_code == (y) || \
336
exc->except_id.except_code == (z)) && \
337
(except_state|=EXCEPT_CAUGHT)) \
338
/* user's code goes here */
339
340
#define CATCH6(u,v,w,x,y,z) \
341
if (except_state == 0 && exc != 0 && \
342
(exc->except_id.except_code == (u) || \
343
exc->except_id.except_code == (v) || \
344
exc->except_id.except_code == (w) || \
345
exc->except_id.except_code == (x) || \
346
exc->except_id.except_code == (y) || \
347
exc->except_id.except_code == (z)) && \
348
(except_state|=EXCEPT_CAUGHT)) \
349
/* user's code goes here */
350
351
#define CATCH7(t, u,v,w,x,y,z) \
352
if (except_state == 0 && exc != 0 && \
353
(exc->except_id.except_code == (t) || \
354
exc->except_id.except_code == (u) || \
355
exc->except_id.except_code == (v) || \
356
exc->except_id.except_code == (w) || \
357
exc->except_id.except_code == (x) || \
358
exc->except_id.except_code == (y) || \
359
exc->except_id.except_code == (z)) && \
360
(except_state|=EXCEPT_CAUGHT)) \
361
/* user's code goes here */
362
363
#define CATCH_ALL \
364
if (except_state == 0 && exc != 0 && \
365
(except_state|=EXCEPT_CAUGHT)) \
366
/* user's code goes here */
367
368
#define FINALLY \
369
if( !(except_state & EXCEPT_FINALLY) && (except_state|=EXCEPT_FINALLY)) \
370
/* user's code goes here */
371
372
#define THROW(x) \
373
except_throw(XCEPT_GROUP_WIRESHARK, (x), NULL)
374
375
#define THROW_ON(cond, x) G_STMT_START { \
376
if ((cond)) \
377
except_throw(XCEPT_GROUP_WIRESHARK, (x), NULL); \
378
} G_STMT_END
379
380
#define THROW_MESSAGE(x, y) \
381
except_throw(XCEPT_GROUP_WIRESHARK, (x), (y))
382
383
#define THROW_MESSAGE_ON(cond, x, y) G_STMT_START { \
384
if ((cond)) \
385
except_throw(XCEPT_GROUP_WIRESHARK, (x), (y)); \
386
} G_STMT_END
387
388
/* Throws a formatted message, its memory is cleared after catching it. */
389
#define THROW_FORMATTED(x, ...) \
390
except_throwf(XCEPT_GROUP_WIRESHARK, (x), __VA_ARGS__)
391
392
/* Like THROW_FORMATTED, but takes a va_list as an argument */
393
#define VTHROW_FORMATTED(x, format, args) \
394
except_vthrowf(XCEPT_GROUP_WIRESHARK, (x), format, args)
395
396
#define GET_MESSAGE except_message(exc)
397
398
#define RETHROW \
399
{ \
400
/* check we're in a catch block */
\
401
g_assert(except_state == EXCEPT_CAUGHT); \
402
/* we can't use except_rethrow here, as that pops a catch block \
403
* off the stack, and we don't want to do that, because we want to \
404
* excecute the FINALLY {} block first. \
405
* except_throw doesn't provide an interface to rethrow an existing \
406
* exception; however, longjmping back to except_try_push() has the \
407
* desired effect. \
408
* \
409
* Note also that THROW and RETHROW should provide much the same \
410
* functionality in terms of which blocks to enter, so any messing \
411
* about with except_state in here would indicate that THROW is \
412
* doing the wrong thing. \
413
*/
\
414
longjmp(except_ch.except_jmp,1); \
415
}
416
417
#define EXCEPT_CODE except_code(exc)
418
419
/* Register cleanup functions in case an exception is thrown and not caught.
420
* From the Kazlib documentation, with modifications for use with the
421
* Wireshark-specific macros:
422
*
423
* CLEANUP_PUSH(func, arg)
424
*
425
* The call to CLEANUP_PUSH shall be matched with a call to
426
* CLEANUP_CALL_AND_POP or CLEANUP_POP which must occur in the same
427
* statement block at the same level of nesting. This requirement allows
428
* an implementation to provide a CLEANUP_PUSH macro which opens up a
429
* statement block and a CLEANUP_POP which closes the statement block.
430
* The space for the registered pointers can then be efficiently
431
* allocated from automatic storage.
432
*
433
* The CLEANUP_PUSH macro registers a cleanup handler that will be
434
* called if an exception subsequently occurs before the matching
435
* CLEANUP_[CALL_AND_]POP is executed, and is not intercepted and
436
* handled by a try-catch region that is nested between the two.
437
*
438
* The first argument to CLEANUP_PUSH is a pointer to the cleanup
439
* handler, a function that returns nothing and takes a single
440
* argument of type void*. The second argument is a void* value that
441
* is registered along with the handler. This value is what is passed
442
* to the registered handler, should it be called.
443
*
444
* Cleanup handlers are called in the reverse order of their nesting:
445
* inner handlers are called before outer handlers.
446
*
447
* The program shall not leave the cleanup region between
448
* the call to the macro CLEANUP_PUSH and the matching call to
449
* CLEANUP_[CALL_AND_]POP by means other than throwing an exception,
450
* or calling CLEANUP_[CALL_AND_]POP.
451
*
452
* Within the call to the cleanup handler, it is possible that new
453
* exceptions may happen. Such exceptions must be handled before the
454
* cleanup handler terminates. If the call to the cleanup handler is
455
* terminated by an exception, the behavior is undefined. The exception
456
* which triggered the cleanup is not yet caught; thus the program
457
* would be effectively trying to replace an exception with one that
458
* isn't in a well-defined state.
459
*
460
*
461
* CLEANUP_POP and CLEANUP_CALL_AND_POP
462
*
463
* A call to the CLEANUP_POP or CLEANUP_CALL_AND_POP macro shall match
464
* each call to CLEANUP_PUSH which shall be in the same statement block
465
* at the same nesting level. It shall match the most recent such a
466
* call that is not matched by a previous CLEANUP_[CALL_AND_]POP at
467
* the same level.
468
*
469
* These macros causes the registered cleanup handler to be removed. If
470
* CLEANUP_CALL_AND_POP is called, the cleanup handler is called.
471
* In that case, the registered context pointer is passed to the cleanup
472
* handler. If CLEANUP_POP is called, the cleanup handler is not called.
473
*
474
* The program shall not leave the region between the call to the
475
* macro CLEANUP_PUSH and the matching call to CLEANUP_[CALL_AND_]POP
476
* other than by throwing an exception, or by executing the
477
* CLEANUP_CALL_AND_POP.
478
*
479
*/
480
481
482
#define CLEANUP_PUSH(f,a) except_cleanup_push((f),(a))
483
#define CLEANUP_POP except_cleanup_pop(0)
484
#define CLEANUP_CALL_AND_POP except_cleanup_pop(1)
485
486
/* Variants to allow nesting of except_cleanup_push w/o "shadowing" variables */
487
#define CLEANUP_PUSH_PFX(pfx,f,a) except_cleanup_push_pfx(pfx,(f),(a))
488
#define CLEANUP_POP_PFX(pfx) except_cleanup_pop_pfx(pfx,0)
489
#define CLEANUP_CALL_AND_POP_PFX(pfx) except_cleanup_pop_pfx(pfx,1)
490
491
492
493
#endif
/* __EXCEPTIONS_H__ */
except.h
Generated by
1.8.11