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