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 11const int32 kMaxSaneStringSize = 4096; // 4 KB 12const int32 kMaxSaneDataSize = 128 * 1024; // 128 KB 13 14// constructor 15Reader::Reader() 16{ 17} 18 19// destructor 20Reader::~Reader() 21{ 22} 23 24// Read 25status_t 26Reader::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 52status_t 53Reader::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 70RequestUnflattener::RequestUnflattener(Reader* reader) 71 : RequestMemberVisitor(), 72 fReader(reader), 73 fStatus(B_OK), 74 fBytesRead(0) 75{ 76} 77 78// GetStatus 79status_t 80RequestUnflattener::GetStatus() const 81{ 82 return fStatus; 83} 84 85// GetBytesRead 86int32 87RequestUnflattener::GetBytesRead() const 88{ 89 return fBytesRead; 90} 91 92// Visit 93void 94RequestUnflattener::Visit(RequestMember* member, bool& data) 95{ 96 uint8 netData; 97 if (Read(&netData, 1) == B_OK) 98 data = netData; 99} 100 101// Visit 102void 103RequestUnflattener::Visit(RequestMember* member, int8& data) 104{ 105 Read(&data, 1); 106} 107 108// Visit 109void 110RequestUnflattener::Visit(RequestMember* member, uint8& data) 111{ 112 Read(&data, 1); 113} 114 115// Visit 116void 117RequestUnflattener::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 124void 125RequestUnflattener::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 132void 133RequestUnflattener::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 140void 141RequestUnflattener::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 148void 149RequestUnflattener::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 156void 157RequestUnflattener::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 164void 165RequestUnflattener::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 185void 186RequestUnflattener::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 207void 208RequestUnflattener::Visit(RequestMember* member, RequestMember& subMember) 209{ 210 subMember.ShowAround(this); 211} 212 213// Visit 214void 215RequestUnflattener::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 227status_t 228RequestUnflattener::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 241status_t 242RequestUnflattener::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 256status_t 257RequestUnflattener::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 280status_t 281RequestUnflattener::ReadBool(bool& data) 282{ 283 return Read(&data, 1); 284} 285 286// ReadInt32 287status_t 288RequestUnflattener::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 298status_t 299RequestUnflattener::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 329status_t 330RequestUnflattener::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