vfs: check userland buffers before reading them.
[haiku.git] / src / kits / debugger / util / BitBuffer.cpp
blob5ba0b135c98abc1a074fe85e7bf06853c7a52af1
1 /*
2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "BitBuffer.h"
10 // #pragma mark - BitReader
13 struct BitBuffer::BitReader {
14 const uint8* data;
15 uint64 bitSize;
16 uint32 bitOffset;
18 BitReader(const uint8* data, uint64 bitSize, uint32 bitOffset)
20 data(data),
21 bitSize(bitSize),
22 bitOffset(bitOffset)
26 uint8 ReadByte()
28 uint8 byte = *data;
29 data++;
30 bitSize -= 8;
32 if (bitOffset == 0)
33 return byte;
35 return (byte << bitOffset) | (*data >> (8 - bitOffset));
38 uint8 ReadBits(uint32 count)
40 uint8 byte = *data;
41 bitSize -= count;
42 bitOffset += count;
44 if (bitOffset <= 8) {
45 if (bitOffset == 8) {
46 bitOffset = 0;
47 data++;
48 return byte & ((1 << count) - 1);
51 return (byte >> (8 - bitOffset)) & ((1 << count) - 1);
54 data++;
55 bitOffset -= 8;
56 return ((byte << bitOffset) | (*data >> (8 - bitOffset)))
57 & ((1 << count) - 1);
62 // #pragma mark - BitBuffer
65 BitBuffer::BitBuffer()
67 fMissingBits(0)
72 BitBuffer::~BitBuffer()
77 bool
78 BitBuffer::AddBytes(const void* data, size_t size)
80 if (size == 0)
81 return true;
83 if (fMissingBits == 0) {
84 size_t oldSize = fBytes.Size();
85 if (!fBytes.AddUninitialized(size))
86 return false;
88 memcpy(fBytes.Elements() + oldSize, data, size);
89 return true;
92 return AddBits(data, (uint64)size * 8, 0);
96 bool
97 BitBuffer::AddBits(const void* _data, uint64 bitSize, uint32 bitOffset)
99 if (bitSize == 0)
100 return true;
102 const uint8* data = (const uint8*)_data + bitOffset / 8;
103 bitOffset %= 8;
105 BitReader reader(data, bitSize, bitOffset);
107 // handle special case first: no more bits than missing
108 size_t oldSize = fBytes.Size();
109 if (fMissingBits > 0 && bitSize <= fMissingBits) {
110 fMissingBits -= bitSize;
111 uint8 bits = reader.ReadBits(bitSize) << fMissingBits;
112 fBytes[oldSize - 1] |= bits;
113 return true;
116 // resize the buffer
117 if (!fBytes.AddUninitialized((reader.bitSize - fMissingBits + 7) / 8))
118 return false;
120 // fill in missing bits
121 if (fMissingBits > 0) {
122 fBytes[oldSize - 1] |= reader.ReadBits(fMissingBits);
123 fMissingBits = 0;
126 // read full bytes as long as we can
127 uint8* buffer = fBytes.Elements() + oldSize;
128 while (reader.bitSize >= 8) {
129 *buffer = reader.ReadByte();
130 buffer++;
133 // If we have left-over bits, write a partial byte.
134 if (reader.bitSize > 0) {
135 fMissingBits = 8 - reader.bitSize;
136 *buffer = reader.ReadBits(reader.bitSize) << fMissingBits;
139 return true;
143 bool
144 BitBuffer::AddZeroBits(uint64 bitSize)
146 if (bitSize == 0)
147 return true;
149 // handle special case first: no more bits than missing
150 size_t oldSize = fBytes.Size();
151 if (fMissingBits > 0 && bitSize <= fMissingBits) {
152 fMissingBits -= bitSize;
153 return true;
156 // resize the buffer
157 if (!fBytes.AddUninitialized((bitSize - fMissingBits + 7) / 8))
158 return false;
160 // fill in missing bits
161 if (fMissingBits > 0) {
162 bitSize -= fMissingBits;
163 fMissingBits = 0;
166 // zero the remaining bytes, including a potentially partial last byte
167 uint8* buffer = fBytes.Elements() + oldSize;
168 memset(buffer, 0, (bitSize + 7) / 8);
169 bitSize %= 8;
171 if (bitSize > 0)
172 fMissingBits = 8 - bitSize;
174 return true;