forked from osmocom/wireshark
Fix and document the CLEANUP_* macros, allowing the programmer to register
cleanup functions for the cases in which an exception is thrown but not caught in a region where cleanup needs to occur. Use these macros in proto_tree_add_item, where we need to free the field_info* in case an exception is thrown when accessing the tvbuff. svn path=/trunk/; revision=2355
This commit is contained in:
parent
a33d2bfcd5
commit
5ad0b0f28c
69
exceptions.h
69
exceptions.h
|
@ -133,8 +133,71 @@
|
|||
|
||||
#define RETHROW except_rethrow(exc)
|
||||
|
||||
#define CLEANUP_CB_PUSH(x,y) except_cleanup_push((x),(y)
|
||||
#define CLEANUP_CB_POP except_cleanup_push(0)
|
||||
#define CLEANUP_CB_CALL_AND_POP except_cleanup_push(1)
|
||||
/* Register cleanup functions in case an exception is thrown and not caught.
|
||||
* From the Kazlib documentation, with modifications for use with the
|
||||
* Ethereal-specific macros:
|
||||
*
|
||||
* CLEANUP_PUSH(func, arg)
|
||||
*
|
||||
* The call to CLEANUP_PUSH shall be matched with a call to
|
||||
* CLEANUP_CALL_AND_POP or CLEANUP_POP which must occur in the same
|
||||
* statement block at the same level of nesting. This requirement allows
|
||||
* an implementation to provide a CLEANUP_PUSH macro which opens up a
|
||||
* statement block and a CLEANUP_POP which closes the statement block.
|
||||
* The space for the registered pointers can then be efficiently
|
||||
* allocated from automatic storage.
|
||||
*
|
||||
* The CLEANUP_PUSH macro registers a cleanup handler that will be
|
||||
* called if an exception subsequently occurs before the matching
|
||||
* CLEANUP_[CALL_AND_]POP is executed, and is not intercepted and
|
||||
* handled by a try-catch region that is nested between the two.
|
||||
*
|
||||
* The first argument to CLEANUP_PUSH is a pointer to the cleanup
|
||||
* handler, a function that returns nothing and takes a single
|
||||
* argument of type void*. The second argument is a void* value that
|
||||
* is registered along with the handler. This value is what is passed
|
||||
* to the registered handler, should it be called.
|
||||
*
|
||||
* Cleanup handlers are called in the reverse order of their nesting:
|
||||
* inner handlers are called before outer handlers.
|
||||
*
|
||||
* The program shall not leave the cleanup region between
|
||||
* the call to the macro CLEANUP_PUSH and the matching call to
|
||||
* CLEANUP_[CALL_AND_]POP by means other than throwing an exception,
|
||||
* or calling CLEANUP_[CALL_AND_]POP.
|
||||
*
|
||||
* Within the call to the cleanup handler, it is possible that new
|
||||
* exceptions may happen. Such exceptions must be handled before the
|
||||
* cleanup handler terminates. If the call to the cleanup handler is
|
||||
* terminated by an exception, the behavior is undefined. The exception
|
||||
* which triggered the cleanup is not yet caught; thus the program
|
||||
* would be effectively trying to replace an exception with one that
|
||||
* isn't in a well-defined state.
|
||||
*
|
||||
*
|
||||
* CLEANUP_POP and CLEANUP_CALL_AND_POP
|
||||
*
|
||||
* A call to the CLEANUP_POP or CLEANUP_CALL_AND_POP macro shall match
|
||||
* each call to CLEANUP_PUSH which shall be in the same statement block
|
||||
* at the same nesting level. It shall match the most recent such a
|
||||
* call that is not matched by a previous CLEANUP_[CALL_AND_]POP at
|
||||
* the same level.
|
||||
*
|
||||
* These macros causes the registered cleanup handler to be removed. If
|
||||
* CLEANUP_CALL_AND_POP is called, the cleanup handler is called.
|
||||
* In that case, the registered context pointer is passed to the cleanup
|
||||
* handler. If CLEANUP_POP is called, the cleanup handler is not called.
|
||||
*
|
||||
* The program shall not leave the region between the call to the
|
||||
* macro CLEANUP_PUSH and the matching call to CLEANUP_[CALL_AND_]POP
|
||||
* other than by throwing an exception, or by executing the
|
||||
* CLEANUP_CALL_AND_POP.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#define CLEANUP_PUSH(f,a) except_cleanup_push((f),(a))
|
||||
#define CLEANUP_POP except_cleanup_pop(0)
|
||||
#define CLEANUP_CALL_AND_POP except_cleanup_pop(1)
|
||||
|
||||
#endif /* __EXCEPTIONS_H__ */
|
||||
|
|
17
proto.c
17
proto.c
|
@ -1,7 +1,7 @@
|
|||
/* proto.c
|
||||
* Routines for protocol tree
|
||||
*
|
||||
* $Id: proto.c,v 1.78 2000/08/22 06:38:18 gram Exp $
|
||||
* $Id: proto.c,v 1.79 2000/08/24 02:55:36 gram Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@zing.org>
|
||||
|
@ -222,6 +222,13 @@ proto_tree_free(proto_tree *tree)
|
|||
g_node_destroy((GNode*)tree);
|
||||
}
|
||||
|
||||
/* We accept a void* instead of a field_info* to satisfy CLEANUP_POP */
|
||||
static void
|
||||
free_field_info(void *fi)
|
||||
{
|
||||
g_mem_chunk_free(gmc_field_info, (field_info*)fi);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
proto_tree_free_node(GNode *node, gpointer data)
|
||||
{
|
||||
|
@ -236,7 +243,7 @@ proto_tree_free_node(GNode *node, gpointer data)
|
|||
g_free(fi->value.string);
|
||||
else if (fi->hfinfo->type == FT_BYTES)
|
||||
g_free(fi->value.bytes);
|
||||
g_mem_chunk_free(gmc_field_info, fi);
|
||||
free_field_info(fi);
|
||||
}
|
||||
return FALSE; /* FALSE = do not end traversal of GNode tree */
|
||||
}
|
||||
|
@ -403,12 +410,15 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|||
proto_item *pi;
|
||||
guint32 value, n;
|
||||
|
||||
/* XXX - need to free this after an exception */
|
||||
new_fi = alloc_field_info(hfindex, tvb, start, length);
|
||||
|
||||
if (new_fi == NULL)
|
||||
return(NULL);
|
||||
|
||||
/* Register a cleanup function in case on of our tvbuff accesses
|
||||
* throws an exception. We need to clean up new_fi. */
|
||||
CLEANUP_PUSH(free_field_info, new_fi);
|
||||
|
||||
switch(new_fi->hfinfo->type) {
|
||||
case FT_NONE:
|
||||
/* no value to set for FT_NONE */
|
||||
|
@ -483,6 +493,7 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
|
|||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
CLEANUP_POP;
|
||||
|
||||
/* Don't add to proto_item to proto_tree until now so that any exceptions
|
||||
* raised by a tvbuff access method doesn't leave junk in the proto_tree. */
|
||||
|
|
Loading…
Reference in New Issue