1 /* 2 * Copyright (c) 2014 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 30 #include <libkern/c++/OSSharedPtr.h> 31 #include <libkern/OSSerializeBinary.h> 32 #include <libkern/c++/OSContainers.h> 33 #include <libkern/c++/OSLib.h> 34 #include <libkern/c++/OSDictionary.h> 35 #include <libkern/OSSerializeBinary.h> 36 #include <libkern/c++/OSSharedPtr.h> 37 38 #include <IOKit/IOLib.h> 39 40 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 41 42 #if 0 43 #define DEBG(fmt, args ...) { kprintf(fmt, args); } 44 #else 45 #define DEBG(fmt, args ...) {} 46 #endif 47 48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 49 50 OSSerialize * 51 OSSerialize::binaryWithCapacity(unsigned int inCapacity, 52 Editor editor, void * reference) 53 { 54 OSSerialize *me; 55 56 if (inCapacity < sizeof(uint32_t)) { 57 return NULL; 58 } 59 me = OSSerialize::withCapacity(inCapacity); 60 if (!me) { 61 return NULL; 62 } 63 64 me->binary = true; 65 me->endCollection = true; 66 me->editor = editor; 67 me->editRef = reference; 68 69 bcopy(kOSSerializeBinarySignature, &me->data[0], sizeof(kOSSerializeBinarySignature)); 70 me->length = sizeof(kOSSerializeBinarySignature); 71 72 return me; 73 } 74 75 bool 76 OSSerialize::addBinary(const void * bits, size_t size) 77 { 78 unsigned int newCapacity; 79 size_t alignSize; 80 81 if (os_add_overflow(size, 3, &alignSize)) { 82 return false; 83 } 84 alignSize &= ~3L; 85 if (os_add_overflow(length, alignSize, &newCapacity)) { 86 return false; 87 } 88 if (newCapacity >= capacity) { 89 newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement; 90 if (newCapacity < capacity) { 91 return false; 92 } 93 if (newCapacity > ensureCapacity(newCapacity)) { 94 return false; 95 } 96 } 97 98 bcopy(bits, &data[length], size); 99 length += alignSize; 100 101 return true; 102 } 103 104 void 105 OSSerialize::setIndexed(bool index __unused) 106 { 107 assert(index && !indexData); 108 indexData = OSData::withCapacity(256); 109 assert(indexData); 110 } 111 112 bool 113 OSSerialize::addBinaryObject(const OSMetaClassBase * o, uint32_t key, 114 const void * bits, uint32_t size, 115 uint32_t * startCollection) 116 { 117 unsigned int newCapacity; 118 size_t alignSize; 119 size_t headerSize; 120 121 // add to tag array 122 tags->setObject(o); 123 124 headerSize = sizeof(key); 125 if (indexData) { 126 uint32_t offset = length; 127 if (startCollection) { 128 *startCollection = offset; 129 headerSize += sizeof(uint32_t); 130 } 131 offset /= sizeof(uint32_t); 132 indexData->appendValue(offset); 133 } 134 135 if (os_add3_overflow(size, headerSize, 3, &alignSize)) { 136 return false; 137 } 138 alignSize &= ~3L; 139 if (os_add_overflow(length, alignSize, &newCapacity)) { 140 return false; 141 } 142 if (newCapacity >= capacity) { 143 newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement; 144 if (newCapacity < capacity) { 145 return false; 146 } 147 if (newCapacity > ensureCapacity(newCapacity)) { 148 return false; 149 } 150 } 151 152 if (endCollection) { 153 endCollection = false; 154 key |= kOSSerializeEndCollecton; 155 } 156 157 bcopy(&key, &data[length], sizeof(key)); 158 bcopy(bits, &data[length + headerSize], size); 159 length += alignSize; 160 161 return true; 162 } 163 164 void 165 OSSerialize::endBinaryCollection(uint32_t startCollection) 166 { 167 uint32_t clength; 168 169 if (!indexData) { 170 return; 171 } 172 173 assert(length > startCollection); 174 if (length <= startCollection) { 175 return; 176 } 177 178 clength = length - startCollection; 179 assert(!(clength & 3)); 180 clength /= sizeof(uint32_t); 181 182 memcpy(&data[startCollection + sizeof(uint32_t)], &clength, sizeof(clength)); 183 } 184 185 bool 186 OSSerialize::binarySerialize(const OSMetaClassBase *o) 187 { 188 bool ok; 189 uint32_t header; 190 191 ok = binarySerializeInternal(o); 192 if (!ok) { 193 return ok; 194 } 195 196 if (indexData) { 197 header = indexData->getLength() / sizeof(uint32_t); 198 assert(header <= kOSSerializeDataMask); 199 header <<= 8; 200 header |= kOSSerializeIndexedBinarySignature; 201 202 memcpy(&data[0], &header, sizeof(header)); 203 } 204 205 return ok; 206 } 207 208 bool 209 OSSerialize::binarySerializeInternal(const OSMetaClassBase *o) 210 { 211 OSDictionary * dict; 212 OSArray * array; 213 OSSet * set; 214 OSNumber * num; 215 OSSymbol * sym; 216 OSString * str; 217 OSData * ldata; 218 OSBoolean * boo; 219 220 unsigned int tagIdx; 221 uint32_t i, key, startCollection = 0; 222 uint32_t len; 223 bool ok; 224 225 tagIdx = tags->getNextIndexOfObject(o, 0); 226 // does it exist? 227 if (-1U != tagIdx) { 228 if (indexData) { 229 assert(indexData->getLength() > (tagIdx * sizeof(uint32_t))); 230 tagIdx = ((const uint32_t *)indexData->getBytesNoCopy())[tagIdx]; 231 assert(tagIdx <= kOSSerializeDataMask); 232 } 233 key = (kOSSerializeObject | tagIdx); 234 if (endCollection) { 235 endCollection = false; 236 key |= kOSSerializeEndCollecton; 237 } 238 ok = addBinary(&key, sizeof(key)); 239 return ok; 240 } 241 242 if ((dict = OSDynamicCast(OSDictionary, o))) { 243 key = (kOSSerializeDictionary | dict->count); 244 ok = addBinaryObject(o, key, NULL, 0, &startCollection); 245 for (i = 0; ok && (i < dict->count);) { 246 const OSSymbol * dictKey; 247 const OSMetaClassBase * dictValue; 248 const OSMetaClassBase * nvalue = NULL; 249 250 dictKey = dict->dictionary[i].key; 251 dictValue = dict->dictionary[i].value; 252 i++; 253 if (editor) { 254 dictValue = nvalue = (*editor)(editRef, this, dict, dictKey, dictValue); 255 if (!dictValue) { 256 dictValue = dict; 257 } 258 } 259 ok = binarySerialize(dictKey); 260 if (!ok) { 261 break; 262 } 263 endCollection = (i == dict->count); 264 ok = binarySerialize(dictValue); 265 if (!ok) { 266 ok = dictValue->serialize(this); 267 } 268 if (nvalue) { 269 nvalue->release(); 270 } 271 // if (!ok) ok = binarySerialize(kOSBooleanFalse); 272 } 273 endBinaryCollection(startCollection); 274 } else if ((array = OSDynamicCast(OSArray, o))) { 275 key = (kOSSerializeArray | array->count); 276 ok = addBinaryObject(o, key, NULL, 0, &startCollection); 277 for (i = 0; ok && (i < array->count);) { 278 i++; 279 endCollection = (i == array->count); 280 ok = binarySerialize(array->array[i - 1]); 281 if (!ok) { 282 ok = array->array[i - 1]->serialize(this); 283 } 284 // if (!ok) ok = binarySerialize(kOSBooleanFalse); 285 } 286 endBinaryCollection(startCollection); 287 } else if ((set = OSDynamicCast(OSSet, o))) { 288 key = (kOSSerializeSet | set->members->count); 289 ok = addBinaryObject(o, key, NULL, 0, &startCollection); 290 for (i = 0; ok && (i < set->members->count);) { 291 i++; 292 endCollection = (i == set->members->count); 293 ok = binarySerialize(set->members->array[i - 1]); 294 if (!ok) { 295 ok = set->members->array[i - 1]->serialize(this); 296 } 297 // if (!ok) ok = binarySerialize(kOSBooleanFalse); 298 } 299 endBinaryCollection(startCollection); 300 } else if ((num = OSDynamicCast(OSNumber, o))) { 301 key = (kOSSerializeNumber | num->size); 302 ok = addBinaryObject(o, key, &num->value, sizeof(num->value), NULL); 303 } else if ((boo = OSDynamicCast(OSBoolean, o))) { 304 key = (kOSSerializeBoolean | (kOSBooleanTrue == boo)); 305 ok = addBinaryObject(o, key, NULL, 0, NULL); 306 } else if ((sym = OSDynamicCast(OSSymbol, o))) { 307 len = (sym->getLength() + 1); 308 key = (kOSSerializeSymbol | len); 309 ok = addBinaryObject(o, key, sym->getCStringNoCopy(), len, NULL); 310 } else if ((str = OSDynamicCast(OSString, o))) { 311 len = str->getLength(); 312 key = (kOSSerializeString | len); 313 ok = addBinaryObject(o, key, str->getCStringNoCopy(), len, NULL); 314 } else if ((ldata = OSDynamicCast(OSData, o))) { 315 len = ldata->getLength(); 316 if (ldata->reserved && ldata->reserved->disableSerialization) { 317 len = 0; 318 } 319 key = (kOSSerializeData | len); 320 ok = addBinaryObject(o, key, ldata->getBytesNoCopy(), len, NULL); 321 } else { 322 return false; 323 } 324 325 return ok; 326 } 327 328 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 329 330 #define setAtIndex(v, idx, o) \ 331 ok = idx < v##Capacity; \ 332 if (!ok && v##Capacity < v##CapacityMax) { \ 333 uint32_t ncap = v##Capacity + 64; \ 334 typeof(v##Array) nbuf = kreallocp_type_container(OSObject *, \ 335 v##Array, v##Capacity, &ncap, Z_WAITOK_ZERO); \ 336 if (nbuf) { \ 337 ok = true; \ 338 v##Array = nbuf; \ 339 v##Capacity = ncap; \ 340 } \ 341 } \ 342 if (ok) v##Array[idx] = o 343 344 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 345 346 OSObject * 347 OSUnserializeBinary(const char *buffer, size_t bufferSize, OSString **errorString) 348 { 349 OSObject ** objsArray; 350 uint32_t objsCapacity; 351 enum { objsCapacityMax = 16 * 1024 * 1024 }; 352 uint32_t objsIdx; 353 354 OSObject ** stackArray; 355 uint32_t stackCapacity; 356 enum { stackCapacityMax = 64 }; 357 uint32_t stackIdx; 358 359 OSObject * result; 360 OSObject * parent; 361 OSDictionary * dict; 362 OSArray * array; 363 OSSet * set; 364 OSDictionary * newDict; 365 OSArray * newArray; 366 OSSet * newSet; 367 OSObject * o; 368 OSSymbol * sym; 369 OSString * str; 370 371 size_t bufferPos; 372 const uint32_t * next; 373 uint32_t key, len, wordLen, length; 374 bool end, newCollect, isRef; 375 union { 376 unsigned long long value; 377 double fpValue; 378 } value; 379 bool ok, indexed, hasLength; 380 381 indexed = false; 382 if (errorString) { 383 *errorString = NULL; 384 } 385 386 if (bufferSize < sizeof(kOSSerializeBinarySignature)) { 387 return NULL; 388 } 389 if (kOSSerializeIndexedBinarySignature == (((const uint8_t *) buffer)[0])) { 390 indexed = true; 391 } else if (0 != strcmp(kOSSerializeBinarySignature, buffer)) { 392 return NULL; 393 } 394 if (3 & ((uintptr_t) buffer)) { 395 return NULL; 396 } 397 398 bufferPos = sizeof(kOSSerializeBinarySignature); 399 next = (typeof(next))(((uintptr_t) buffer) + bufferPos); 400 401 DEBG("---------OSUnserializeBinary(%p)\n", buffer); 402 403 objsArray = stackArray = NULL; 404 objsIdx = objsCapacity = 0; 405 stackIdx = stackCapacity = 0; 406 407 result = NULL; 408 parent = NULL; 409 dict = NULL; 410 array = NULL; 411 set = NULL; 412 sym = NULL; 413 414 ok = true; 415 while (ok) { 416 bufferPos += sizeof(*next); 417 if (!(ok = (bufferPos <= bufferSize))) { 418 break; 419 } 420 key = *next++; 421 length = 0; 422 423 len = (key & kOSSerializeDataMask); 424 wordLen = (len + 3) >> 2; 425 end = (0 != (kOSSerializeEndCollecton & key)); 426 DEBG("key 0x%08x: 0x%04x, %d\n", key, len, end); 427 428 newCollect = isRef = hasLength = false; 429 o = NULL; newDict = NULL; newArray = NULL; newSet = NULL; 430 431 switch (kOSSerializeTypeMask & key) { 432 case kOSSerializeDictionary: 433 o = newDict = OSDictionary::withCapacity(len); 434 newCollect = (len != 0); 435 hasLength = indexed; 436 break; 437 case kOSSerializeArray: 438 o = newArray = OSArray::withCapacity(len); 439 newCollect = (len != 0); 440 hasLength = indexed; 441 break; 442 case kOSSerializeSet: 443 o = newSet = OSSet::withCapacity(len); 444 newCollect = (len != 0); 445 hasLength = indexed; 446 break; 447 448 case kOSSerializeObject: 449 if (len >= objsIdx) { 450 break; 451 } 452 o = objsArray[len]; 453 isRef = true; 454 break; 455 456 case kOSSerializeNumber: 457 bufferPos += sizeof(long long); 458 if (bufferPos > bufferSize) { 459 break; 460 } 461 value.value = next[1]; 462 value.value <<= 32; 463 value.value |= next[0]; 464 switch (len) { 465 case 63: 466 o = OSNumber::withDouble(value.fpValue); 467 break; 468 case 31: 469 o = OSNumber::withFloat((float) value.fpValue); 470 break; 471 case 64: 472 case 32: 473 case 16: 474 case 8: 475 o = OSNumber::withNumber(value.value, len); 476 break; 477 } 478 next += 2; 479 break; 480 481 case kOSSerializeSymbol: 482 bufferPos += (wordLen * sizeof(uint32_t)); 483 if (bufferPos > bufferSize) { 484 break; 485 } 486 if (len < 1) { 487 break; 488 } 489 if (0 != ((const char *)next)[len - 1]) { 490 break; 491 } 492 o = (OSObject *) OSSymbol::withCString((const char *) next); 493 next += wordLen; 494 break; 495 496 case kOSSerializeString: 497 bufferPos += (wordLen * sizeof(uint32_t)); 498 if (bufferPos > bufferSize) { 499 break; 500 } 501 o = OSString::withCString((const char *) next, len); 502 next += wordLen; 503 break; 504 505 case kOSSerializeData: 506 bufferPos += (wordLen * sizeof(uint32_t)); 507 if (bufferPos > bufferSize) { 508 break; 509 } 510 o = OSData::withBytes(next, len); 511 next += wordLen; 512 break; 513 514 case kOSSerializeBoolean: 515 o = (len ? kOSBooleanTrue : kOSBooleanFalse); 516 break; 517 518 default: 519 break; 520 } 521 522 if (!(ok = (o != NULL))) { 523 break; 524 } 525 526 if (hasLength) { 527 bufferPos += sizeof(*next); 528 if (!(ok = (bufferPos <= bufferSize))) { 529 o->release(); 530 break; 531 } 532 length = *next++; 533 } 534 535 if (!isRef) { 536 setAtIndex(objs, objsIdx, o); 537 if (!ok) { 538 o->release(); 539 break; 540 } 541 objsIdx++; 542 } 543 544 if (dict) { 545 if (!sym) { 546 sym = (OSSymbol *) o; 547 } else { 548 str = sym; 549 sym = OSDynamicCast(OSSymbol, sym); 550 if (!sym && (str = OSDynamicCast(OSString, str))) { 551 sym = const_cast<OSSymbol *>(OSSymbol::withString(str)); 552 ok = (sym != NULL); 553 if (!ok) { 554 break; 555 } 556 } 557 DEBG("%s = %s\n", sym->getCStringNoCopy(), o->getMetaClass()->getClassName()); 558 if (o != dict) { 559 ok = dict->setObject(sym, o); 560 } 561 if (sym && (sym != str)) { 562 sym->release(); 563 } 564 sym = NULL; 565 } 566 } else if (array) { 567 ok = array->setObject(o); 568 } else if (set) { 569 ok = set->setObject(o); 570 } else if (result) { 571 ok = false; 572 } else { 573 assert(!parent); 574 result = o; 575 } 576 577 if (!ok) { 578 break; 579 } 580 581 if (end) { 582 parent = NULL; 583 } 584 if (newCollect) { 585 stackIdx++; 586 setAtIndex(stack, stackIdx, parent); 587 if (!ok) { 588 break; 589 } 590 DEBG("++stack[%d] %p\n", stackIdx, parent); 591 parent = o; 592 dict = newDict; 593 array = newArray; 594 set = newSet; 595 end = false; 596 } 597 598 if (end) { 599 while (stackIdx) { 600 parent = stackArray[stackIdx]; 601 DEBG("--stack[%d] %p\n", stackIdx, parent); 602 stackIdx--; 603 if (parent) { 604 break; 605 } 606 } 607 if (!parent) { 608 break; 609 } 610 set = NULL; 611 dict = NULL; 612 array = NULL; 613 if (!(dict = OSDynamicCast(OSDictionary, parent))) { 614 if (!(array = OSDynamicCast(OSArray, parent))) { 615 ok = (NULL != (set = OSDynamicCast(OSSet, parent))); 616 } 617 } 618 } 619 } 620 DEBG("ret %p\n", result); 621 622 if (!ok) { 623 result = NULL; 624 } 625 626 if (objsCapacity) { 627 for (len = (result != NULL); len < objsIdx; len++) { 628 objsArray[len]->release(); 629 } 630 kfree_type(OSObject *, objsCapacity, objsArray); 631 } 632 if (stackCapacity) { 633 kfree_type(OSObject *, stackCapacity, stackArray); 634 } 635 636 return result; 637 } 638 639 OSObject* 640 OSUnserializeXML( 641 const char * buffer, 642 OSSharedPtr<OSString>& errorString) 643 { 644 OSString* errorStringRaw = NULL; 645 OSObject* result = OSUnserializeXML(buffer, &errorStringRaw); 646 errorString.reset(errorStringRaw, OSNoRetain); 647 return result; 648 } 649 650 OSObject* 651 OSUnserializeXML( 652 const char * buffer, 653 size_t bufferSize, 654 OSSharedPtr<OSString> &errorString) 655 { 656 OSString* errorStringRaw = NULL; 657 OSObject* result = OSUnserializeXML(buffer, bufferSize, &errorStringRaw); 658 errorString.reset(errorStringRaw, OSNoRetain); 659 return result; 660 } 661 662 OSObject* 663 OSUnserializeBinary(const char *buffer, size_t bufferSize, OSSharedPtr<OSString>& errorString) 664 { 665 OSString* errorStringRaw = NULL; 666 OSObject* result = OSUnserializeBinary(buffer, bufferSize, &errorStringRaw); 667 errorString.reset(errorStringRaw, OSNoRetain); 668 return result; 669 } 670 671 OSObject* 672 OSUnserialize(const char *buffer, OSSharedPtr<OSString>& errorString) 673 { 674 OSString* errorStringRaw = NULL; 675 OSObject* result = OSUnserialize(buffer, &errorStringRaw); 676 errorString.reset(errorStringRaw, OSNoRetain); 677 return result; 678 } 679