Add a "tvb_ensure_bytes_exist()", which is like "tvb_bytes_exist()" only

it throws the appropriate exception if the bytes don't exist.  Use it in
the GIOP and ASN.1 code to check whether the bytes to be copied to a
buffer exist before allocating the buffer.

Make "check_offset_length_no_exception()" check for an overflow, so that
it can be used in "tvb_ensure_bytes_exist()" and do all the checking
that the code "tvb_ensure_bytes_exist()" replaces did.

Make "get_CDR_wchar()" return a "gint", so that if the length octet it
fetched has a value between 128 and 255, the length can be returned
correctly.

Fix some comments not to specify the exception thrown by various
routines that can throw various exceptions.

svn path=/trunk/; revision=5453
This commit is contained in:
Guy Harris 2002-05-13 01:24:47 +00:00
parent ef67bf2d2f
commit b6e941027f
5 changed files with 91 additions and 51 deletions

34
asn1.c
View File

@ -1,7 +1,7 @@
/* asn1.c
* Routines for ASN.1 BER dissection
*
* $Id: asn1.c,v 1.12 2002/03/05 09:18:58 guy Exp $
* $Id: asn1.c,v 1.13 2002/05/13 01:24:45 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -655,27 +655,15 @@ asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
int eoc;
guchar *ptr;
eoc = asn1->offset + enc_len;
/*
* Check for an overflow, and clamp "eoc" at the maximum if we
* get it.
*/
if (eoc < asn1->offset || eoc < 0)
eoc = INT_MAX;
/*
* First, make sure the entire string is in the tvbuff, and throw
* an exception if it isn't. If the length is bogus, this should
* keep us from trying to allocate an immensely large buffer.
* (It won't help if the length is *valid* but immensely large,
* but that's another matter.)
*
* We do that by attempting to fetch the last byte (if the length
* isn't 0).
*/
if (enc_len != 0) {
tvb_get_guint8(asn1->tvb, eoc - 1);
tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
*octets = g_malloc (enc_len);
} else {
/*
@ -686,6 +674,8 @@ asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
*/
*octets = g_malloc (1);
}
eoc = asn1->offset + enc_len;
ptr = *octets;
while (asn1->offset < eoc) {
ret = asn1_octet_decode (asn1, (guchar *)ptr++);
@ -832,27 +822,17 @@ asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
guint size;
subid_t *optr;
eoc = asn1->offset + enc_len;
/*
* Check for an overflow, and clamp "eoc" at the maximum if we
* get it.
*/
if (eoc < asn1->offset || eoc < 0)
eoc = INT_MAX;
/*
* First, make sure the entire string is in the tvbuff, and throw
* an exception if it isn't. If the length is bogus, this should
* keep us from trying to allocate an immensely large buffer.
* (It won't help if the length is *valid* but immensely large,
* but that's another matter.)
*
* We do that by attempting to fetch the last byte (if the length
* isn't 0).
*/
if (enc_len != 0)
tvb_get_guint8(asn1->tvb, eoc - 1);
tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
eoc = asn1->offset + enc_len;
size = enc_len + 1;
*oid = g_malloc(size * sizeof(gulong));

View File

@ -9,7 +9,7 @@
* the data of a backing tvbuff, or can be a composite of
* other tvbuffs.
*
* $Id: tvbuff.c,v 1.36 2002/05/05 21:07:52 guy Exp $
* $Id: tvbuff.c,v 1.37 2002/05/13 01:24:47 guy Exp $
*
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
*
@ -421,16 +421,38 @@ static gboolean
check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
guint *offset_ptr, guint *length_ptr, int *exception)
{
guint end_offset;
g_assert(tvb->initialized);
if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
return FALSE;
}
if (*offset_ptr + *length_ptr <= tvb->length) {
/*
* Compute the offset of the first byte past the length.
*/
end_offset = *offset_ptr + *length_ptr;
/*
* Check for an overflow, and clamp "end_offset" at the maximum
* if we got an overflow - that should force us to indicate that
* we're past the end of the tvbuff.
*/
if (end_offset < *offset_ptr)
end_offset = UINT_MAX;
/*
* Check whether that offset goes more than one byte past the
* end of the buffer.
*
* If not, return TRUE; otherwise, return FALSE and, if "exception"
* is non-null, return the appropriate exception through it.
*/
if (end_offset <= tvb->length) {
return TRUE;
}
else if (*offset_ptr + *length_ptr <= tvb->reported_length) {
else if (end_offset <= tvb->reported_length) {
if (exception) {
*exception = BoundsError;
}
@ -446,7 +468,7 @@ check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
g_assert_not_reached();
}
/* Checks (+/-) offset and length and throws BoundsError if
/* Checks (+/-) offset and length and throws an exception if
* either is out of bounds. Sets integer ptrs to the new offset
* and length. */
static void
@ -625,7 +647,7 @@ tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
/* Validates that 'length' bytes are available starting from
* offset (pos/neg). Does not throw BoundsError exception. */
* offset (pos/neg). Does not throw an exception. */
gboolean
tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
{
@ -644,6 +666,31 @@ tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
}
}
/* Validates that 'length' bytes are available starting from
* offset (pos/neg). Throws an exception if they aren't. */
void
tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
{
guint abs_offset, abs_length;
g_assert(tvb->initialized);
/*
* -1 doesn't mean "until end of buffer", as that's pointless
* for this routine. We must treat it as a Really Large Positive
* Number, so that we throw an exception; we throw
* ReportedBoundsError, as if it were past even the end of a
* reassembled packet, and past the end of even the data we
* didn't capture.
*
* We do the same with other negative lengths.
*/
if (length < 0) {
THROW(ReportedBoundsError);
}
check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
}
gboolean
tvb_offset_exists(tvbuff_t *tvb, gint offset)
{
@ -950,6 +997,17 @@ tvb_memcpy(tvbuff_t *tvb, guint8* target, gint offset, gint length)
}
/*
* XXX - this doesn't treat a length of -1 as an error.
* If it did, this could replace some code that calls
* "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
* data to it.
*
* Does anything depend on this routine treating -1 as meaning "to the
* end of the buffer"? If so, perhaps we need two routines, one that
* treats -1 as such, and one that checks for -1 and then calls this
* routine.
*/
guint8*
tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
{

View File

@ -9,7 +9,7 @@
* the data of a backing tvbuff, or can be a composite of
* other tvbuffs.
*
* $Id: tvbuff.h,v 1.26 2002/05/05 00:57:59 guy Exp $
* $Id: tvbuff.h,v 1.27 2002/05/13 01:24:47 guy Exp $
*
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
*
@ -192,13 +192,17 @@ extern guint tvb_length(tvbuff_t*);
* indicate that offset is out of bounds. No exception is thrown. */
extern gint tvb_length_remaining(tvbuff_t*, gint offset);
/* Same as above, but throws BoundsError if the offset is out of bounds. */
/* Same as above, but throws an exception if the offset is out of bounds. */
extern guint tvb_ensure_length_remaining(tvbuff_t*, gint offset);
/* Checks (w/o throwing exception) that the bytes referred to by
* 'offset'/'length' actually exist in the buffer */
extern gboolean tvb_bytes_exist(tvbuff_t*, gint offset, gint length);
/* Checks that the bytes referred to by 'offset'/'length' actually exist
* in the buffer, and throws an exception if they aren't. */
extern void tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length);
/* Checks (w/o throwing exception) that offset exists in buffer */
extern gboolean tvb_offset_exists(tvbuff_t*, gint offset);
@ -223,7 +227,7 @@ extern void tvb_set_reported_length(tvbuff_t*, guint);
extern gint tvb_raw_offset(tvbuff_t*);
/************** START OF ACCESSORS ****************/
/* All accessors will throw BoundsError or ReportedBoundsError if appropriate */
/* All accessors will throw an exception if appropriate */
extern guint8 tvb_get_guint8(tvbuff_t*, gint offset);

View File

@ -9,7 +9,7 @@
* Frank Singleton <frank.singleton@ericsson.com>
* Trevor Shepherd <eustrsd@am1.ericsson.se>
*
* $Id: packet-giop.c,v 1.60 2002/05/12 20:43:29 gerald Exp $
* $Id: packet-giop.c,v 1.61 2002/05/13 01:24:45 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -2327,17 +2327,15 @@ guint8 get_CDR_octet(tvbuff_t *tvb, int *offset) {
void get_CDR_octet_seq(tvbuff_t *tvb, gchar **seq, int *offset, guint32 len) {
guint32 remain_len = tvb_length_remaining(tvb, *offset);
if (remain_len < len) {
/*
* Generate an exception, and stop processing.
* We do that now, rather than after allocating the buffer, so we
* don't have to worry about freeing the buffer.
* XXX - would we be better off using a cleanup routine?
*/
tvb_ensure_length_remaining(tvb, *offset + remain_len + 1);
}
/*
* Make sure that the entire sequence of octets is in the buffer before
* allocating the buffer, so that we don't have to worry about freeing
* the buffer, and so that we don't try to allocate a buffer bigger
* than the data we'll actually be copying, and thus don't run the risk
* of crashing if the buffer is *so* big that we fail to allocate it
* and "g_new0()" aborts.
*/
tvb_ensure_bytes_exist(tvb, *offset, len);
/*
* XXX - should we just allocate "len" bytes, and have "get_CDR_string()"
@ -2639,9 +2637,9 @@ guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset, gboolean stream_is_big_endian
* Wchar is not supported for GIOP 1.0.
*/
gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset, MessageHeader * header) {
guint32 slength;
gint slength;
gchar *raw_wstring;
/* CORBA chapter 15:

View File

@ -4,7 +4,7 @@
*
* Based on CORBAv2.4.2 Chapter 15 GIOP Description.
*
* $Id: packet-giop.h,v 1.8 2002/05/12 20:43:29 gerald Exp $
* $Id: packet-giop.h,v 1.9 2002/05/13 01:24:46 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
@ -484,7 +484,7 @@ extern guint16 get_CDR_ushort(tvbuff_t *tvb, int *offset,
* Wchar is not supported for GIOP 1.0.
*/
extern gint8 get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset,
extern gint get_CDR_wchar(tvbuff_t *tvb, gchar **seq, int *offset,
MessageHeader * header);