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(capacity: 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, dst: &me->data[0], n: 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(src: bits, dst: &data[length], n: 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(capacity: 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 ; |
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(value: 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(src: &key, dst: &data[length], n: sizeof(key)); |
158 | bcopy(src: bits, dst: &data[length + headerSize], n: 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(dst: &data[startCollection + sizeof(uint32_t)], src: &clength, n: sizeof(clength)); |
183 | } |
184 | |
185 | bool |
186 | OSSerialize::binarySerialize(const OSMetaClassBase *o) |
187 | { |
188 | bool ok; |
189 | uint32_t ; |
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(dst: &data[0], src: &header, n: 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(anObject: o, index: 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(bits: &key, size: sizeof(key)); |
239 | return ok; |
240 | } |
241 | |
242 | if ((dict = OSDynamicCast(OSDictionary, o))) { |
243 | key = (kOSSerializeDictionary | dict->count); |
244 | ok = addBinaryObject(o, key, NULL, size: 0, startCollection: &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(o: dictKey); |
260 | if (!ok) { |
261 | break; |
262 | } |
263 | endCollection = (i == dict->count); |
264 | ok = binarySerialize(o: dictValue); |
265 | if (!ok) { |
266 | ok = dictValue->serialize(serializer: 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, size: 0, startCollection: &startCollection); |
277 | for (i = 0; ok && (i < array->count);) { |
278 | i++; |
279 | endCollection = (i == array->count); |
280 | ok = binarySerialize(o: array->array[i - 1]); |
281 | if (!ok) { |
282 | ok = array->array[i - 1]->serialize(serializer: 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, size: 0, startCollection: &startCollection); |
290 | for (i = 0; ok && (i < set->members->count);) { |
291 | i++; |
292 | endCollection = (i == set->members->count); |
293 | ok = binarySerialize(o: set->members->array[i - 1]); |
294 | if (!ok) { |
295 | ok = set->members->array[i - 1]->serialize(serializer: 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, bits: &num->value, size: sizeof(num->value), NULL); |
303 | } else if ((boo = OSDynamicCast(OSBoolean, o))) { |
304 | key = (kOSSerializeBoolean | (kOSBooleanTrue == boo)); |
305 | ok = addBinaryObject(o, key, NULL, size: 0, NULL); |
306 | } else if ((sym = OSDynamicCast(OSSymbol, o))) { |
307 | len = (sym->getLength() + 1); |
308 | key = (kOSSerializeSymbol | len); |
309 | ok = addBinaryObject(o, key, bits: sym->getCStringNoCopy(), size: len, NULL); |
310 | } else if ((str = OSDynamicCast(OSString, o))) { |
311 | len = str->getLength(); |
312 | key = (kOSSerializeString | len); |
313 | ok = addBinaryObject(o, key, bits: str->getCStringNoCopy(), size: 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, bits: ldata->getBytesNoCopy(), size: 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, s2: 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(capacity: len); |
434 | newCollect = (len != 0); |
435 | hasLength = indexed; |
436 | break; |
437 | case kOSSerializeArray: |
438 | o = newArray = OSArray::withCapacity(capacity: len); |
439 | newCollect = (len != 0); |
440 | hasLength = indexed; |
441 | break; |
442 | case kOSSerializeSet: |
443 | o = newSet = OSSet::withCapacity(capacity: 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: value.fpValue); |
467 | break; |
468 | case 31: |
469 | o = OSNumber::withFloat(value: (float) value.fpValue); |
470 | break; |
471 | case 64: |
472 | case 32: |
473 | case 16: |
474 | case 8: |
475 | o = OSNumber::withNumber(value: value.value, numberOfBits: 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(cString: (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(cString: (const char *) next, length: 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(bytes: next, numBytes: 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(aString: 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(aKey: sym, anObject: 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, errorString: &errorStringRaw); |
646 | errorString.reset(p: 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, errorString: &errorStringRaw); |
658 | errorString.reset(p: 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, errorString: &errorStringRaw); |
667 | errorString.reset(p: 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, errorString: &errorStringRaw); |
676 | errorString.reset(p: errorStringRaw, OSNoRetain); |
677 | return result; |
678 | } |
679 | |