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 15 Reader::Reader() 16 { 17 } 18 19 // destructor 20 Reader::~Reader() 21 { 22 } 23 24 // Read 25 status_t 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 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 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 80 RequestUnflattener::GetStatus() const 81 { 82 return fStatus; 83 } 84 85 // GetBytesRead 86 int32 87 RequestUnflattener::GetBytesRead() const 88 { 89 return fBytesRead; 90 } 91 92 // Visit 93 void 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 103 RequestUnflattener::Visit(RequestMember* member, int8& data) 104 { 105 Read(&data, 1); 106 } 107 108 // Visit 109 void 110 RequestUnflattener::Visit(RequestMember* member, uint8& data) 111 { 112 Read(&data, 1); 113 } 114 115 // Visit 116 void 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 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 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 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 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 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 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 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 208 RequestUnflattener::Visit(RequestMember* member, RequestMember& subMember) 209 { 210 subMember.ShowAround(this); 211 } 212 213 // Visit 214 void 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 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 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 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 281 RequestUnflattener::ReadBool(bool& data) 282 { 283 return Read(&data, 1); 284 } 285 286 // ReadInt32 287 status_t 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 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 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