aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/tvbuff.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/epan/tvbuff.c b/epan/tvbuff.c
index 6e36c23397..2a5bed0215 100644
--- a/epan/tvbuff.c
+++ b/epan/tvbuff.c
@@ -115,13 +115,24 @@ tvb_new(const tvbuff_type type)
return tvb;
}
+static const unsigned char left_aligned_bitmask[] = {
+ 0xff,
+ 0x80,
+ 0xc0,
+ 0xe0,
+ 0xf0,
+ 0xf8,
+ 0xfc,
+ 0xfe
+};
+
tvbuff_t *
tvb_new_octet_aligned(tvbuff_t *tvb, guint32 bit_offset, gint32 no_of_bits)
{
tvbuff_t *sub_tvb = NULL;
guint32 byte_offset;
gint32 datalen, i;
- guint8 left, right, *buf;
+ guint8 left, right, remaining_bits, *buf;
const guint8 *data;
byte_offset = bit_offset >> 3;
@@ -130,9 +141,13 @@ tvb_new_octet_aligned(tvbuff_t *tvb, guint32 bit_offset, gint32 no_of_bits)
if (no_of_bits == -1) {
datalen = tvb_length_remaining(tvb, byte_offset);
+ remaining_bits = 0;
} else {
datalen = no_of_bits >> 3;
- if (no_of_bits % 8) datalen++;
+ remaining_bits = no_of_bits % 8;
+ if (remaining_bits){
+ datalen++;
+ }
}
/* already aligned -> shortcut */
@@ -149,14 +164,17 @@ tvb_new_octet_aligned(tvbuff_t *tvb, guint32 bit_offset, gint32 no_of_bits)
*/
if (tvb_length_remaining(tvb, byte_offset) > datalen) {
data = tvb_get_ptr(tvb, byte_offset, datalen + 1);
+ /* shift tvb data bit_offset bits to the left */
+ for (i = 0; i < datalen; i++)
+ buf[i] = (data[i] << left) | (data[i+1] >> right);
} else {
data = tvb_get_ptr(tvb, byte_offset, datalen);
- datalen--; /* correct 'datalen' for 'for' loop */
- buf[datalen] = data[datalen] << left; /* set last octet */
+ /* shift tvb data bit_offset bits to the left */
+ for (i = 0; i < (datalen-1); i++)
+ buf[i] = (data[i] << left) | (data[i+1] >> right);
+ buf[datalen-1] = data[datalen] << left; /* set last octet */
}
- /* shift tvb data bit_offset bits to the left */
- for (i = 0; i < datalen; i++)
- buf[i] = (data[i] << left) | (data[i+1] >> right);
+ buf[datalen-1] &= left_aligned_bitmask[remaining_bits];
sub_tvb = tvb_new_child_real_data(tvb, buf, datalen, datalen);