1 // RequestUnflattener.cpp
2
3 #include <stdlib.h>
4
5 #include <ByteOrder.h>
6
7 #include "Compatibility.h"
8 #include "DebugSupport.h"
9 #include "RequestUnflattener.h"
10
11 const int32 kMaxSaneStringSize = 4096; // 4 KB
12 const int32 kMaxSaneDataSize = 128 * 1024; // 128 KB
13
14 // constructor
Reader()15 Reader::Reader()
16 {
17 }
18
19 // destructor
~Reader()20 Reader::~Reader()
21 {
22 }
23
24 // Read
25 status_t
Read(int32 size,void ** buffer,bool * mustFree)26 Reader::Read(int32 size, void** buffer, bool* mustFree)
27 {
28 // check params
29 if (size < 0 || !buffer || !mustFree)
30 return B_BAD_VALUE;
31
32 // deal with size == 0
33 if (size == 0) {
34 *buffer = NULL;
35 *mustFree = false;
36 return B_OK;
37 }
38
39 // allocate the buffer and read
40 *buffer = malloc(size);
41 if (!*buffer)
42 return B_NO_MEMORY;
43 status_t error = Read(*buffer, size);
44 if (error != B_OK) {
45 free(*buffer);
46 return error;
47 }
48 return error;
49 }
50
51 // Skip
52 status_t
Skip(int32 size)53 Reader::Skip(int32 size)
54 {
55 if (size <= 0)
56 return B_OK;
57
58 if (size > 8)
59 return B_BAD_VALUE;
60
61 char buffer[8];
62 return Read(buffer, size);
63 }
64
65
66
67 // RequestUnflattener
68
69 // constructor
RequestUnflattener(Reader * reader)70 RequestUnflattener::RequestUnflattener(Reader* reader)
71 : RequestMemberVisitor(),
72 fReader(reader),
73 fStatus(B_OK),
74 fBytesRead(0)
75 {
76 }
77
78 // GetStatus
79 status_t
GetStatus() const80 RequestUnflattener::GetStatus() const
81 {
82 return fStatus;
83 }
84
85 // GetBytesRead
86 int32
GetBytesRead() const87 RequestUnflattener::GetBytesRead() const
88 {
89 return fBytesRead;
90 }
91
92 // Visit
93 void
Visit(RequestMember * member,bool & data)94 RequestUnflattener::Visit(RequestMember* member, bool& data)
95 {
96 uint8 netData;
97 if (Read(&netData, 1) == B_OK)
98 data = netData;
99 }
100
101 // Visit
102 void
Visit(RequestMember * member,int8 & data)103 RequestUnflattener::Visit(RequestMember* member, int8& data)
104 {
105 Read(&data, 1);
106 }
107
108 // Visit
109 void
Visit(RequestMember * member,uint8 & data)110 RequestUnflattener::Visit(RequestMember* member, uint8& data)
111 {
112 Read(&data, 1);
113 }
114
115 // Visit
116 void
Visit(RequestMember * member,int16 & data)117 RequestUnflattener::Visit(RequestMember* member, int16& data)
118 {
119 if (Read(&data, 2) == B_OK)
120 data = B_BENDIAN_TO_HOST_INT16(data);
121 }
122
123 // Visit
124 void
Visit(RequestMember * member,uint16 & data)125 RequestUnflattener::Visit(RequestMember* member, uint16& data)
126 {
127 if (Read(&data, 2) == B_OK)
128 data = B_BENDIAN_TO_HOST_INT16(data);
129 }
130
131 // Visit
132 void
Visit(RequestMember * member,int32 & data)133 RequestUnflattener::Visit(RequestMember* member, int32& data)
134 {
135 if (Read(&data, 4) == B_OK)
136 data = B_BENDIAN_TO_HOST_INT32(data);
137 }
138
139 // Visit
140 void
Visit(RequestMember * member,uint32 & data)141 RequestUnflattener::Visit(RequestMember* member, uint32& data)
142 {
143 if (Read(&data, 4) == B_OK)
144 data = B_BENDIAN_TO_HOST_INT32(data);
145 }
146
147 // Visit
148 void
Visit(RequestMember * member,int64 & data)149 RequestUnflattener::Visit(RequestMember* member, int64& data)
150 {
151 if (Read(&data, 8) == B_OK)
152 data = B_BENDIAN_TO_HOST_INT64(data);
153 }
154
155 // Visit
156 void
Visit(RequestMember * member,uint64 & data)157 RequestUnflattener::Visit(RequestMember* member, uint64& data)
158 {
159 if (Read(&data, 8) == B_OK)
160 data = B_BENDIAN_TO_HOST_INT64(data);
161 }
162
163 // Visit
164 void
Visit(RequestMember * member,Data & data)165 RequestUnflattener::Visit(RequestMember* member, Data& data)
166 {
167 void* buffer;
168 int32 size;
169 bool mustFree;
170 if (ReadData(buffer, size, mustFree) != B_OK)
171 return;
172
173 // we can't deal with mustFree buffers currently
174 if (mustFree) {
175 free(buffer);
176 fStatus = B_ERROR;
177 return;
178 }
179
180 data.address = buffer;
181 data.size = size;
182 }
183
184 // Visit
185 void
Visit(RequestMember * member,StringData & data)186 RequestUnflattener::Visit(RequestMember* member, StringData& data)
187 {
188 void* buffer;
189 int32 size;
190 bool mustFree;
191 if (ReadData(buffer, size, mustFree) != B_OK)
192 return;
193
194 // we can't deal with mustFree buffers currently
195 if (mustFree) {
196 free(buffer);
197 fStatus = B_ERROR;
198 return;
199 }
200
201 data.address = buffer;
202 data.size = size;
203 // TODO: Check null termination.
204 }
205
206 // Visit
207 void
Visit(RequestMember * member,RequestMember & subMember)208 RequestUnflattener::Visit(RequestMember* member, RequestMember& subMember)
209 {
210 subMember.ShowAround(this);
211 }
212
213 // Visit
214 void
Visit(RequestMember * member,FlattenableRequestMember & subMember)215 RequestUnflattener::Visit(RequestMember* member,
216 FlattenableRequestMember& subMember)
217 {
218 if (fStatus != B_OK)
219 return;
220
221 status_t status = subMember.Unflatten(this);
222 if (fStatus == B_OK)
223 fStatus = status;
224 }
225
226 // Read
227 status_t
Read(void * buffer,int32 size)228 RequestUnflattener::Read(void* buffer, int32 size)
229 {
230 if (fStatus != B_OK)
231 return fStatus;
232
233 fStatus = fReader->Read(buffer, size);
234 if (fStatus == B_OK)
235 fBytesRead += size;
236
237 return fStatus;
238 }
239
240 // Read
241 status_t
Read(int32 size,void * & buffer,bool & mustFree)242 RequestUnflattener::Read(int32 size, void*& buffer, bool& mustFree)
243 {
244 if (fStatus != B_OK)
245 return fStatus;
246
247 fStatus = fReader->Read(size, &buffer, &mustFree);
248 if (fStatus == B_OK)
249 fBytesRead += size;
250
251 return fStatus;
252 }
253
254
255 // Align
256 status_t
Align(int32 align)257 RequestUnflattener::Align(int32 align)
258 {
259 if (fStatus != B_OK)
260 return fStatus;
261
262 if (align > 1) {
263 int32 newBytesRead = fBytesRead;
264 if (!(align & 0x3))
265 newBytesRead = (fBytesRead + 3) & ~0x3;
266 else if (!(align & 0x1))
267 newBytesRead = (fBytesRead + 1) & ~0x1;
268
269 if (newBytesRead > fBytesRead) {
270 fStatus = fReader->Skip(newBytesRead - fBytesRead);
271 if (fStatus == B_OK)
272 fBytesRead = newBytesRead;
273 }
274 }
275
276 return fStatus;
277 }
278
279 // ReadBool
280 status_t
ReadBool(bool & data)281 RequestUnflattener::ReadBool(bool& data)
282 {
283 return Read(&data, 1);
284 }
285
286 // ReadInt32
287 status_t
ReadInt32(int32 & data)288 RequestUnflattener::ReadInt32(int32& data)
289 {
290 if (Read(&data, 4) == B_OK)
291 data = B_BENDIAN_TO_HOST_INT32(data);
292
293 return fStatus;
294 }
295
296
297 // ReadData
298 status_t
ReadData(void * & buffer,int32 & _size,bool & mustFree)299 RequestUnflattener::ReadData(void*& buffer, int32& _size, bool& mustFree)
300 {
301 if (fStatus != B_OK)
302 return fStatus;
303
304 // read size
305 int32 size;
306 if (ReadInt32(size) != B_OK)
307 return fStatus;
308
309 // check size for sanity
310 if (size < 0 || size > kMaxSaneDataSize) {
311 fStatus = B_BAD_DATA;
312 return fStatus;
313 }
314
315 // read data
316 if (size > 0) {
317 if (Read(size, buffer, mustFree) != B_OK)
318 return fStatus;
319 } else {
320 buffer = NULL;
321 mustFree = false;
322 }
323
324 _size = size;
325 return fStatus;
326 }
327
328 // ReadString
329 status_t
ReadString(HashString & string)330 RequestUnflattener::ReadString(HashString& string)
331 {
332 void* buffer;
333 int32 size;
334 bool mustFree;
335 if (ReadData(buffer, size, mustFree) == B_OK) {
336 if (!string.SetTo((const char*)buffer))
337 fStatus = B_NO_MEMORY;
338
339 if (mustFree)
340 free(buffer);
341 }
342
343 return fStatus;
344 }
345
346