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