vfs: check userland buffers before reading them.
[haiku.git] / src / kits / app / PropertyInfo.cpp
blob3df949b123980816ef04ffc8e3043019c74ede6f
1 /*
2 * Copyright 2001-2005 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marc Flerackers (mflerackers@androme.be)
7 */
10 #include <ByteOrder.h>
11 #include <DataIO.h>
12 #include <Message.h>
13 #include <PropertyInfo.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
20 BPropertyInfo::BPropertyInfo(property_info* propertyInfo, value_info* valueInfo,
21 bool freeOnDelete)
23 fPropInfo(propertyInfo),
24 fValueInfo(valueInfo),
25 fPropCount(0),
26 fInHeap(freeOnDelete),
27 fValueCount(0)
29 if (fPropInfo != NULL) {
30 while (fPropInfo[fPropCount].name)
31 fPropCount++;
34 if (fValueInfo != NULL) {
35 while (fValueInfo[fValueCount].name)
36 fValueCount++;
41 BPropertyInfo::~BPropertyInfo()
43 FreeMem();
47 int32 BPropertyInfo::FindMatch(BMessage* message, int32 index,
48 BMessage* specifier, int32 form, const char* property, void* data) const
50 int32 propertyIndex = 0;
52 while (fPropInfo != NULL && fPropInfo[propertyIndex].name != NULL) {
53 property_info* propertyInfo = fPropInfo + propertyIndex;
55 if (!strcmp(propertyInfo->name, property)
56 && FindCommand(message->what, index, propertyInfo)
57 && FindSpecifier(form, propertyInfo)) {
58 if (data)
59 *((uint32*)data) = propertyInfo->extra_data;
61 return propertyIndex;
63 propertyIndex++;
66 return B_ERROR;
70 bool
71 BPropertyInfo::IsFixedSize() const
73 return false;
77 type_code
78 BPropertyInfo::TypeCode() const
80 return B_PROPERTY_INFO_TYPE;
84 ssize_t
85 BPropertyInfo::FlattenedSize() const
87 size_t size = (2 * sizeof(int32)) + 1;
89 if (fPropInfo) {
90 // Main chunks
91 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
92 size += strlen(fPropInfo[pi].name) + 1;
94 if (fPropInfo[pi].usage)
95 size += strlen(fPropInfo[pi].usage) + 1;
96 else
97 size += sizeof(char);
99 size += sizeof(int32);
101 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++)
102 size += sizeof(int32);
103 size += sizeof(int32);
105 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++)
106 size += sizeof(int32);
107 size += sizeof(int32);
110 // Type chunks
111 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
112 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++)
113 size += sizeof(int32);
114 size += sizeof(int32);
116 for (int32 i = 0; i < 3
117 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++) {
118 for (int32 j = 0; j < 5
119 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++) {
120 size += strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1;
121 size += sizeof(int32);
123 size += sizeof(int32);
125 size += sizeof(int32);
129 if (fValueInfo) {
130 size += sizeof(int16);
132 // Chunks
133 for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) {
134 size += sizeof(int32);
135 size += sizeof(int32);
137 size += strlen(fValueInfo[vi].name) + 1;
139 if (fValueInfo[vi].usage)
140 size += strlen(fValueInfo[vi].usage) + 1;
141 else
142 size += sizeof(char);
144 size += sizeof(int32);
148 return size;
152 status_t
153 BPropertyInfo::Flatten(void* buffer, ssize_t numBytes) const
155 if (numBytes < FlattenedSize())
156 return B_NO_MEMORY;
158 if (buffer == NULL)
159 return B_BAD_VALUE;
161 BMemoryIO flatData(buffer, numBytes);
163 char tmpChar = B_HOST_IS_BENDIAN;
164 int32 tmpInt;
166 flatData.Write(&tmpChar, sizeof(tmpChar));
167 flatData.Write(&fPropCount, sizeof(fPropCount));
168 tmpInt = 0x01 | (fValueInfo ? 0x2 : 0x0);
169 flatData.Write(&tmpInt, sizeof(tmpInt));
171 if (fPropInfo) {
172 // Main chunks
173 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
174 flatData.Write(fPropInfo[pi].name, strlen(fPropInfo[pi].name) + 1);
175 if (fPropInfo[pi].usage != NULL) {
176 flatData.Write(fPropInfo[pi].usage, strlen(fPropInfo[pi].usage)
177 + 1);
178 } else {
179 tmpChar = 0;
180 flatData.Write(&tmpChar, sizeof(tmpChar));
183 flatData.Write(&fPropInfo[pi].extra_data,
184 sizeof(fPropInfo[pi].extra_data));
186 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++) {
187 flatData.Write(&fPropInfo[pi].commands[i],
188 sizeof(fPropInfo[pi].commands[i]));
190 tmpInt = 0;
191 flatData.Write(&tmpInt, sizeof(tmpInt));
193 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) {
194 flatData.Write(&fPropInfo[pi].specifiers[i],
195 sizeof(fPropInfo[pi].specifiers[i]));
197 tmpInt = 0;
198 flatData.Write(&tmpInt, sizeof(tmpInt));
201 // Type chunks
202 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
203 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) {
204 flatData.Write(&fPropInfo[pi].types[i],
205 sizeof(fPropInfo[pi].types[i]));
207 tmpInt = 0;
208 flatData.Write(&tmpInt, sizeof(tmpInt));
210 for (int32 i = 0; i < 3
211 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++) {
212 for (int32 j = 0; j < 5
213 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++) {
214 flatData.Write(fPropInfo[pi].ctypes[i].pairs[j].name,
215 strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1);
216 flatData.Write(&fPropInfo[pi].ctypes[i].pairs[j].type,
217 sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
219 tmpInt = 0;
220 flatData.Write(&tmpInt, sizeof(tmpInt));
222 tmpInt = 0;
223 flatData.Write(&tmpInt, sizeof(tmpInt));
227 if (fValueInfo) {
228 // Value Chunks
229 flatData.Write(&fValueCount, sizeof(fValueCount));
230 for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) {
231 flatData.Write(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
232 flatData.Write(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
233 flatData.Write(fValueInfo[vi].name, strlen(fValueInfo[vi].name)
234 + 1);
235 if (fValueInfo[vi].usage) {
236 flatData.Write(fValueInfo[vi].usage,
237 strlen(fValueInfo[vi].usage) + 1);
238 } else {
239 tmpChar = 0;
240 flatData.Write(&tmpChar, sizeof(tmpChar));
242 flatData.Write(&fValueInfo[vi].extra_data,
243 sizeof(fValueInfo[vi].extra_data));
247 return B_OK;
251 bool
252 BPropertyInfo::AllowsTypeCode(type_code code) const
254 return code == B_PROPERTY_INFO_TYPE;
258 status_t
259 BPropertyInfo::Unflatten(type_code code, const void* buffer,
260 ssize_t numBytes)
262 if (!AllowsTypeCode(code))
263 return B_BAD_TYPE;
265 if (buffer == NULL)
266 return B_BAD_VALUE;
268 FreeMem();
270 BMemoryIO flatData(buffer, numBytes);
271 char tmpChar = B_HOST_IS_BENDIAN;
272 int32 tmpInt;
274 flatData.Read(&tmpChar, sizeof(tmpChar));
275 bool swapRequired = (tmpChar != B_HOST_IS_BENDIAN);
277 flatData.Read(&fPropCount, sizeof(fPropCount));
279 int32 flags;
280 flatData.Read(&flags, sizeof(flags));
281 if (swapRequired) {
282 fPropCount = B_SWAP_INT32(fPropCount);
283 flags = B_SWAP_INT32(flags);
286 if (flags & 1) {
287 fPropInfo = static_cast<property_info *>(malloc(sizeof(property_info)
288 * (fPropCount + 1)));
289 memset(fPropInfo, 0, (fPropCount + 1) * sizeof(property_info));
291 // Main chunks
292 for (int32 pi = 0; pi < fPropCount; pi++) {
293 fPropInfo[pi].name = strdup(static_cast<const char*>(buffer)
294 + flatData.Position());
295 flatData.Seek(strlen(fPropInfo[pi].name) + 1, SEEK_CUR);
297 fPropInfo[pi].usage = strdup(static_cast<const char *>(buffer)
298 + flatData.Position());
299 flatData.Seek(strlen(fPropInfo[pi].usage) + 1, SEEK_CUR);
301 flatData.Read(&fPropInfo[pi].extra_data,
302 sizeof(fPropInfo[pi].extra_data));
303 if (swapRequired) {
304 fPropInfo[pi].extra_data
305 = B_SWAP_INT32(fPropInfo[pi].extra_data);
308 flatData.Read(&tmpInt, sizeof(tmpInt));
309 for (int32 i = 0; tmpInt != 0; i++) {
310 if (swapRequired) {
311 tmpInt = B_SWAP_INT32(tmpInt);
313 fPropInfo[pi].commands[i] = tmpInt;
314 flatData.Read(&tmpInt, sizeof(tmpInt));
317 flatData.Read(&tmpInt, sizeof(tmpInt));
318 for (int32 i = 0; tmpInt != 0; i++) {
319 if (swapRequired) {
320 tmpInt = B_SWAP_INT32(tmpInt);
322 fPropInfo[pi].specifiers[i] = tmpInt;
323 flatData.Read(&tmpInt, sizeof(tmpInt));
327 // Type chunks
328 for (int32 pi = 0; pi < fPropCount; pi++) {
329 flatData.Read(&tmpInt, sizeof(tmpInt));
330 for (int32 i = 0; tmpInt != 0; i++) {
331 if (swapRequired) {
332 tmpInt = B_SWAP_INT32(tmpInt);
334 fPropInfo[pi].types[i] = tmpInt;
335 flatData.Read(&tmpInt, sizeof(tmpInt));
338 flatData.Read(&tmpInt, sizeof(tmpInt));
339 for (int32 i = 0; tmpInt != 0; i++) {
340 for (int32 j = 0; tmpInt != 0; j++) {
341 flatData.Seek(-sizeof(tmpInt), SEEK_CUR);
342 fPropInfo[pi].ctypes[i].pairs[j].name =
343 strdup(static_cast<const char *>(buffer)
344 + flatData.Position());
345 flatData.Seek(strlen(fPropInfo[pi].ctypes[i].pairs[j].name)
346 + 1, SEEK_CUR);
348 flatData.Read(&fPropInfo[pi].ctypes[i].pairs[j].type,
349 sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
350 if (swapRequired) {
351 fPropInfo[pi].ctypes[i].pairs[j].type =
352 B_SWAP_INT32(fPropInfo[pi].ctypes[i].pairs[j].type);
354 flatData.Read(&tmpInt, sizeof(tmpInt));
356 flatData.Read(&tmpInt, sizeof(tmpInt));
361 if (flags & 2) {
362 flatData.Read(&fValueCount, sizeof(fValueCount));
363 if (swapRequired) {
364 fValueCount = B_SWAP_INT16(fValueCount);
367 fValueInfo = static_cast<value_info *>(malloc(sizeof(value_info)
368 * (fValueCount + 1)));
369 memset(fValueInfo, 0, (fValueCount + 1) * sizeof(value_info));
371 for (int32 vi = 0; vi < fValueCount; vi++) {
372 flatData.Read(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
373 flatData.Read(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
375 fValueInfo[vi].name = strdup(static_cast<const char *>(buffer)
376 + flatData.Position());
377 flatData.Seek(strlen(fValueInfo[vi].name) + 1, SEEK_CUR);
379 fValueInfo[vi].usage = strdup(static_cast<const char *>(buffer)
380 + flatData.Position());
381 flatData.Seek(strlen(fValueInfo[vi].usage) + 1, SEEK_CUR);
383 flatData.Read(&fValueInfo[vi].extra_data,
384 sizeof(fValueInfo[vi].extra_data));
385 if (swapRequired) {
386 fValueInfo[vi].kind = static_cast<value_kind>(
387 B_SWAP_INT32(fValueInfo[vi].kind));
388 fValueInfo[vi].value = B_SWAP_INT32(fValueInfo[vi].value);
389 fValueInfo[vi].extra_data
390 = B_SWAP_INT32(fValueInfo[vi].extra_data);
395 return B_OK;
399 const property_info*
400 BPropertyInfo::Properties() const
402 return fPropInfo;
406 const value_info*
407 BPropertyInfo::Values() const
409 return fValueInfo;
413 int32
414 BPropertyInfo::CountProperties() const
416 return fPropCount;
420 int32
421 BPropertyInfo::CountValues() const
423 return fValueCount;
427 void
428 BPropertyInfo::PrintToStream() const
430 printf(" property commands types "
431 " specifiers\n");
432 printf("-------------------------------------------------------------------"
433 "-------------\n");
435 for (int32 pi = 0; fPropInfo[pi].name != 0; pi++) {
436 // property
437 printf("%14s", fPropInfo[pi].name);
438 // commands
439 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++) {
440 uint32 command = fPropInfo[pi].commands[i];
442 printf(" %c%c%c%-28c", int(command & 0xFF000000) >> 24,
443 int(command & 0xFF0000) >> 16, int(command & 0xFF00) >> 8,
444 int(command) & 0xFF);
446 // types
447 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) {
448 uint32 type = fPropInfo[pi].types[i];
450 printf("%c%c%c%c", int(type & 0xFF000000) >> 24,
451 int(type & 0xFF0000) >> 16, int(type & 0xFF00) >> 8,
452 (int)type & 0xFF);
454 // specifiers
455 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) {
456 uint32 spec = fPropInfo[pi].specifiers[i];
457 printf("%" B_PRIu32, spec);
459 printf("\n");
464 bool
465 BPropertyInfo::FindCommand(uint32 what, int32 index,
466 property_info* propertyInfo)
468 bool result = false;
470 if (propertyInfo->commands[0] == 0) {
471 result = true;
472 } else if (index == 0) {
473 for (int32 i = 0; i < 10 && propertyInfo->commands[i] != 0; i++) {
474 if (propertyInfo->commands[i] == what) {
475 result = true;
476 break;
481 return result;
485 bool
486 BPropertyInfo::FindSpecifier(uint32 form, property_info* propertyInfo)
488 bool result = false;
490 if (propertyInfo->specifiers[0] == 0) {
491 result = true;
492 } else {
493 for (int32 i = 0; i < 10 && propertyInfo->specifiers[i] != 0; i++) {
494 if (propertyInfo->specifiers[i] == form) {
495 result = true;
496 break;
501 return result;
505 void BPropertyInfo::_ReservedPropertyInfo1() {}
506 void BPropertyInfo::_ReservedPropertyInfo2() {}
507 void BPropertyInfo::_ReservedPropertyInfo3() {}
508 void BPropertyInfo::_ReservedPropertyInfo4() {}
511 BPropertyInfo::BPropertyInfo(const BPropertyInfo &)
516 BPropertyInfo&
517 BPropertyInfo::operator=(const BPropertyInfo &)
519 return *this;
523 void
524 BPropertyInfo::FreeMem()
526 int i, j, k;
528 if (!fInHeap)
529 return;
531 if (fPropInfo != NULL) {
532 for (i = 0; i < fPropCount; i++) {
533 free((char *)fPropInfo[i].name);
534 free((char *)fPropInfo[i].usage);
536 for (j = 0; j < 3; j++) {
537 for (k = 0; k < 5; k++) {
538 if (fPropInfo[i].ctypes[j].pairs[k].name == NULL)
539 break;
541 free((char *)fPropInfo[i].ctypes[j].pairs[k].name);
544 if (fPropInfo[i].ctypes[j].pairs[0].name == NULL)
545 break;
548 free(fPropInfo);
549 fPropInfo = NULL;
550 fPropCount = 0;
553 if (fValueInfo != NULL) {
554 for (i = 0; i < fValueCount; i++) {
555 free((char *)fValueInfo[i].name);
556 free((char *)fValueInfo[i].usage);
558 free(fValueInfo);
559 fValueInfo = NULL;
560 fValueCount = 0;
563 fInHeap = false;