Loading...
--- xnu/xnu-3248.50.21/libkern/c++/OSSerializeBinary.cpp
+++ xnu/xnu-3789.31.2/libkern/c++/OSSerializeBinary.cpp
@@ -69,12 +69,13 @@
unsigned int newCapacity;
size_t alignSize;
- alignSize = ((size + 3) & ~3L);
- newCapacity = length + alignSize;
+ if (os_add_overflow(size, 3, &alignSize)) return (false);
+ alignSize &= ~3L;
+ if (os_add_overflow(length, alignSize, &newCapacity)) return (false);
if (newCapacity >= capacity)
{
newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
- if (newCapacity < ensureCapacity(newCapacity)) return (false);
+ if (newCapacity > ensureCapacity(newCapacity)) return (false);
}
bcopy(bits, &data[length], size);
@@ -88,21 +89,17 @@
{
unsigned int newCapacity;
size_t alignSize;
- OSNumber * tagNum;
-
- // build a tag
- tagNum = OSNumber::withNumber(tag, 32);
- tag++;
- // add to tag dictionary
- tags->setObject((const OSSymbol *) o, tagNum);
- tagNum->release();
-
- alignSize = ((size + sizeof(key) + 3) & ~3L);
- newCapacity = length + alignSize;
+
+ // add to tag array
+ tags->setObject(o);
+
+ if (os_add3_overflow(size, sizeof(key), 3, &alignSize)) return (false);
+ alignSize &= ~3L;
+ if (os_add_overflow(length, alignSize, &newCapacity)) return (false);
if (newCapacity >= capacity)
{
newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement;
- if (newCapacity < ensureCapacity(newCapacity)) return (false);
+ if (newCapacity > ensureCapacity(newCapacity)) return (false);
}
if (endCollection)
@@ -126,19 +123,19 @@
OSNumber * num;
OSSymbol * sym;
OSString * str;
- OSData * data;
+ OSData * ldata;
OSBoolean * boo;
- OSNumber * tagNum;
+ unsigned int tagIdx;
uint32_t i, key;
size_t len;
bool ok;
- tagNum = (OSNumber *)tags->getObject((const OSSymbol *) o);
+ tagIdx = tags->getNextIndexOfObject(o, 0);
// does it exist?
- if (tagNum)
- {
- key = (kOSSerializeObject | tagNum->unsigned32BitValue());
+ if (-1U != tagIdx)
+ {
+ key = (kOSSerializeObject | tagIdx);
if (endCollection)
{
endCollection = false;
@@ -158,9 +155,9 @@
const OSMetaClassBase * dictValue;
const OSMetaClassBase * nvalue = 0;
+ dictKey = dict->dictionary[i].key;
+ dictValue = dict->dictionary[i].value;
i++;
- dictKey = dict->dictionary[i-1].key;
- dictValue = dict->dictionary[i-1].value;
if (editor)
{
dictValue = nvalue = (*editor)(editRef, this, dict, dictKey, dictValue);
@@ -223,12 +220,12 @@
key = (kOSSerializeString | len);
ok = addBinaryObject(o, key, str->getCStringNoCopy(), len);
}
- else if ((data = OSDynamicCast(OSData, o)))
- {
- len = data->getLength();
- if (data->reserved && data->reserved->disableSerialization) len = 0;
+ else if ((ldata = OSDynamicCast(OSData, o)))
+ {
+ len = ldata->getLength();
+ if (ldata->reserved && ldata->reserved->disableSerialization) len = 0;
key = (kOSSerializeData | len);
- ok = addBinaryObject(o, key, data->getBytesNoCopy(), len);
+ ok = addBinaryObject(o, key, ldata->getBytesNoCopy(), len);
}
else return (false);
@@ -237,20 +234,27 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#define setAtIndex(v, idx, o) \
- if (idx >= v##Capacity) \
- { \
- uint32_t ncap = v##Capacity + 64; \
- typeof(v##Array) nbuf = (typeof(v##Array)) kalloc_container(ncap * sizeof(o)); \
- if (!nbuf) ok = false; \
- if (v##Array) \
- { \
- bcopy(v##Array, nbuf, v##Capacity * sizeof(o)); \
- kfree(v##Array, v##Capacity * sizeof(o)); \
- } \
- v##Array = nbuf; \
- v##Capacity = ncap; \
- } \
+#define setAtIndex(v, idx, o) \
+ if (idx >= v##Capacity) \
+ { \
+ if (v##Capacity >= v##CapacityMax) ok = false; \
+ else \
+ { \
+ uint32_t ncap = v##Capacity + 64; \
+ typeof(v##Array) nbuf = (typeof(v##Array)) kalloc_container(ncap * sizeof(o)); \
+ if (!nbuf) ok = false; \
+ else \
+ { \
+ if (v##Array) \
+ { \
+ bcopy(v##Array, nbuf, v##Capacity * sizeof(o)); \
+ kfree(v##Array, v##Capacity * sizeof(o)); \
+ } \
+ v##Array = nbuf; \
+ v##Capacity = ncap; \
+ } \
+ } \
+ } \
if (ok) v##Array[idx] = o;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -260,10 +264,12 @@
{
OSObject ** objsArray;
uint32_t objsCapacity;
+ enum { objsCapacityMax = 16*1024*1024 };
uint32_t objsIdx;
OSObject ** stackArray;
uint32_t stackCapacity;
+ enum { stackCapacityMax = 64 };
uint32_t stackIdx;
OSObject * result;
@@ -286,9 +292,9 @@
bool ok;
if (errorString) *errorString = 0;
+ if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (NULL);
if (0 != strcmp(kOSSerializeBinarySignature, buffer)) return (NULL);
if (3 & ((uintptr_t) buffer)) return (NULL);
- if (bufferSize < sizeof(kOSSerializeBinarySignature)) return (NULL);
bufferPos = sizeof(kOSSerializeBinarySignature);
next = (typeof(next)) (((uintptr_t) buffer) + bufferPos);
@@ -338,13 +344,13 @@
case kOSSerializeObject:
if (len >= objsIdx) break;
o = objsArray[len];
- o->retain();
isRef = true;
break;
case kOSSerializeNumber:
bufferPos += sizeof(long long);
if (bufferPos > bufferSize) break;
+ if ((len != 32) && (len != 64) && (len != 16) && (len != 8)) break;
value = next[1];
value <<= 32;
value |= next[0];
@@ -355,6 +361,7 @@
case kOSSerializeSymbol:
bufferPos += (wordLen * sizeof(uint32_t));
if (bufferPos > bufferSize) break;
+ if (len < 2) break;
if (0 != ((const char *)next)[len-1]) break;
o = (OSObject *) OSSymbol::withCString((const char *) next);
next += wordLen;
@@ -387,42 +394,36 @@
if (!isRef)
{
setAtIndex(objs, objsIdx, o);
- if (!ok) break;
+ if (!ok)
+ {
+ o->release();
+ break;
+ }
objsIdx++;
}
if (dict)
{
- if (sym)
+ if (!sym) sym = (OSSymbol *) o;
+ else
{
+ str = sym;
+ sym = OSDynamicCast(OSSymbol, sym);
+ if (!sym && (str = OSDynamicCast(OSString, str)))
+ {
+ sym = (OSSymbol *) OSSymbol::withString(str);
+ ok = (sym != 0);
+ if (!ok) break;
+ }
DEBG("%s = %s\n", sym->getCStringNoCopy(), o->getMetaClass()->getClassName());
- if (o != dict) ok = dict->setObject(sym, o, true);
- o->release();
- sym->release();
+ if (o != dict) ok = dict->setObject(sym, o);
+ if (sym && (sym != str)) sym->release();
sym = 0;
}
- else
- {
- sym = OSDynamicCast(OSSymbol, o);
- if (!sym && (str = OSDynamicCast(OSString, o)))
- {
- sym = (OSSymbol *) OSSymbol::withString(str);
- o->release();
- o = 0;
- }
- ok = (sym != 0);
- }
- }
- else if (array)
- {
- ok = array->setObject(o);
- o->release();
- }
- else if (set)
- {
- ok = set->setObject(o);
- o->release();
- }
+ }
+ else if (array) ok = array->setObject(o);
+ else if (set) ok = set->setObject(o);
+ else if (result) ok = false;
else
{
assert(!parent);
@@ -431,14 +432,12 @@
if (!ok) break;
+ if (end) parent = 0;
if (newCollect)
{
- if (!end)
- {
- stackIdx++;
- setAtIndex(stack, stackIdx, parent);
- if (!ok) break;
- }
+ stackIdx++;
+ setAtIndex(stack, stackIdx, parent);
+ if (!ok) break;
DEBG("++stack[%d] %p\n", stackIdx, parent);
parent = o;
dict = newDict;
@@ -449,11 +448,15 @@
if (end)
{
- if (!stackIdx) break;
- parent = stackArray[stackIdx];
- DEBG("--stack[%d] %p\n", stackIdx, parent);
- stackIdx--;
- set = 0;
+ while (stackIdx)
+ {
+ parent = stackArray[stackIdx];
+ DEBG("--stack[%d] %p\n", stackIdx, parent);
+ stackIdx--;
+ if (parent) break;
+ }
+ if (!parent) break;
+ set = 0;
dict = 0;
array = 0;
if (!(dict = OSDynamicCast(OSDictionary, parent)))
@@ -464,13 +467,14 @@
}
DEBG("ret %p\n", result);
- if (objsCapacity) kfree(objsArray, objsCapacity * sizeof(*objsArray));
+ if (!ok) result = 0;
+
+ if (objsCapacity)
+ {
+ for (len = (result != 0); len < objsIdx; len++) objsArray[len]->release();
+ kfree(objsArray, objsCapacity * sizeof(*objsArray));
+ }
if (stackCapacity) kfree(stackArray, stackCapacity * sizeof(*stackArray));
- if (!ok && result)
- {
- result->release();
- result = 0;
- }
return (result);
}