Index: src/OFData+MessagePackValue.m ================================================================== --- src/OFData+MessagePackValue.m +++ src/OFData+MessagePackValue.m @@ -26,50 +26,51 @@ #import "OFMessagePackExtension.h" #import "OFNull.h" #import "OFNumber.h" #import "OFString.h" +#import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" +#import "OFOutOfRangeException.h" +#import "OFTruncatedDataException.h" int _OFData_MessagePackValue_reference; -static size_t parseObject(const uint8_t *buffer, size_t length, id *object, - size_t depthLimit); +static size_t parseObject(const unsigned char *buffer, size_t length, + id *object, size_t depthLimit); static uint16_t -readUInt16(const uint8_t *buffer) +readUInt16(const unsigned char *buffer) { return ((uint16_t)buffer[0] << 8) | buffer[1]; } static uint32_t -readUInt32(const uint8_t *buffer) +readUInt32(const unsigned char *buffer) { return ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) | ((uint32_t)buffer[2] << 8) | buffer[3]; } static uint64_t -readUInt64(const uint8_t *buffer) +readUInt64(const unsigned char *buffer) { return ((uint64_t)buffer[0] << 56) | ((uint64_t)buffer[1] << 48) | ((uint64_t)buffer[2] << 40) | ((uint64_t)buffer[3] << 32) | ((uint64_t)buffer[4] << 24) | ((uint64_t)buffer[5] << 16) | ((uint64_t)buffer[6] << 8) | buffer[7]; } static size_t -parseArray(const uint8_t *buffer, size_t length, id *object, size_t count, +parseArray(const unsigned char *buffer, size_t length, id *object, size_t count, size_t depthLimit) { void *pool; size_t pos = 0; - if (--depthLimit == 0) { - *object = nil; - return 0; - } + if (--depthLimit == 0) + @throw [OFOutOfRangeException exception]; /* * Don't use capacity! For data and strings, this is safe, as we can * check if we still have enough bytes left. For an array however, we * can't know this, as every child can be more than one byte. @@ -76,23 +77,15 @@ */ *object = [OFMutableArray array]; for (size_t i = 0; i < count; i++) { id child; - size_t childLength; pool = objc_autoreleasePoolPush(); - childLength = parseObject(buffer + pos, length - pos, &child, + pos += parseObject(buffer + pos, length - pos, &child, depthLimit); - if (childLength == 0 || child == nil) { - objc_autoreleasePoolPop(pool); - - *object = nil; - return 0; - } - pos += childLength; [*object addObject: child]; objc_autoreleasePoolPop(pool); } @@ -99,20 +92,18 @@ return pos; } static size_t -parseTable(const uint8_t *buffer, size_t length, id *object, size_t count, +parseTable(const unsigned char *buffer, size_t length, id *object, size_t count, size_t depthLimit) { void *pool; size_t pos = 0; - if (--depthLimit == 0) { - *object = nil; - return 0; - } + if (--depthLimit == 0) + @throw [OFOutOfRangeException exception]; /* * Don't use capacity! For data and strings, this is safe, as we can * check if we still have enough bytes left. For a dictionary however, * we can't know this, as every key / value can be more than one byte. @@ -119,33 +110,17 @@ */ *object = [OFMutableDictionary dictionary]; for (size_t i = 0; i < count; i++) { id key, value; - size_t keyLength, valueLength; pool = objc_autoreleasePoolPush(); - keyLength = parseObject(buffer + pos, length - pos, &key, - depthLimit); - if (keyLength == 0 || key == nil) { - objc_autoreleasePoolPop(pool); - - *object = nil; - return 0; - } - pos += keyLength; - - valueLength = parseObject(buffer + pos, length - pos, &value, - depthLimit); - if (valueLength == 0 || value == nil) { - objc_autoreleasePoolPop(pool); - - *object = nil; - return 0; - } - pos += valueLength; + pos += parseObject(buffer + pos, length - pos, &key, + depthLimit); + pos += parseObject(buffer + pos, length - pos, &value, + depthLimit); [*object setObject: value forKey: key]; objc_autoreleasePoolPop(pool); @@ -205,18 +180,18 @@ data: data]; } } static size_t -parseObject(const uint8_t *buffer, size_t length, id *object, +parseObject(const unsigned char *buffer, size_t length, id *object, size_t depthLimit) { size_t count; OFData *data; if (length < 1) - goto error; + @throw [OFTruncatedDataException exception]; /* positive fixint */ if ((buffer[0] & 0x80) == 0) { *object = [OFNumber numberWithUInt8: buffer[0] & 0x7F]; return 1; @@ -231,11 +206,11 @@ /* fixstr */ if ((buffer[0] & 0xE0) == 0xA0) { count = buffer[0] & 0x1F; if (length < count + 1) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFString stringWithUTF8String: (const char *)buffer + 1 length: count]; return count + 1; @@ -254,79 +229,79 @@ /* Prefix byte */ switch (buffer[0]) { /* Unsigned integers */ case 0xCC: /* uint8 */ if (length < 2) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithUInt8: buffer[1]]; return 2; case 0xCD: /* uint 16 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithUInt16: readUInt16(buffer + 1)]; return 3; case 0xCE: /* uint 32 */ if (length < 5) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithUInt32: readUInt32(buffer + 1)]; return 5; case 0xCF: /* uint 64 */ if (length < 9) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithUInt64: readUInt64(buffer + 1)]; return 9; /* Signed integers */ case 0xD0: /* int 8 */ if (length < 2) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithInt8: buffer[1]]; return 2; case 0xD1: /* int 16 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithInt16: readUInt16(buffer + 1)]; return 3; case 0xD2: /* int 32 */ if (length < 5) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithInt32: readUInt32(buffer + 1)]; return 5; case 0xD3: /* int 64 */ if (length < 9) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFNumber numberWithInt64: readUInt64(buffer + 1)]; return 9; /* Floating point */ case 0xCA:; /* float 32 */ union { - uint8_t u8[4]; + unsigned char u8[4]; float f; } f; if (length < 5) - goto error; + @throw [OFTruncatedDataException exception]; memcpy(&f.u8, buffer + 1, 4); *object = [OFNumber numberWithFloat: OF_BSWAP_FLOAT_IF_LE(f.f)]; return 5; case 0xCB:; /* float 64 */ union { - uint8_t u8[8]; + unsigned char u8[8]; double d; } d; if (length < 9) - goto error; + @throw [OFTruncatedDataException exception]; memcpy(&d.u8, buffer + 1, 8); *object = [OFNumber numberWithDouble: OF_BSWAP_DOUBLE_IF_LE(d.d)]; @@ -344,56 +319,56 @@ *object = [OFNumber numberWithBool: true]; return 1; /* Data */ case 0xC4: /* bin 8 */ if (length < 2) - goto error; + @throw [OFTruncatedDataException exception]; count = buffer[1]; if (length < count + 2) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFData dataWithItems: buffer + 2 count: count]; return count + 2; case 0xC5: /* bin 16 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; count = readUInt16(buffer + 1); if (length < count + 3) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFData dataWithItems: buffer + 3 count: count]; return count + 3; case 0xC6: /* bin 32 */ if (length < 5) - goto error; + @throw [OFTruncatedDataException exception]; count = readUInt32(buffer + 1); if (length < count + 5) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFData dataWithItems: buffer + 5 count: count]; return count + 5; /* Extensions */ case 0xC7: /* ext 8 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; count = buffer[1]; if (length < count + 3) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 3 count: count]; @try { *object = createExtension(buffer[2], data); @@ -402,16 +377,16 @@ } return count + 3; case 0xC8: /* ext 16 */ if (length < 4) - goto error; + @throw [OFTruncatedDataException exception]; count = readUInt16(buffer + 1); if (length < count + 4) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 4 count: count]; @try { *object = createExtension(buffer[3], data); @@ -420,16 +395,16 @@ } return count + 4; case 0xC9: /* ext 32 */ if (length < 6) - goto error; + @throw [OFTruncatedDataException exception]; count = readUInt32(buffer + 1); if (length < count + 6) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 6 count: count]; @try { *object = createExtension(buffer[5], data); @@ -438,11 +413,11 @@ } return count + 6; case 0xD4: /* fixext 1 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 2 count: 1]; @try { *object = createExtension(buffer[1], data); @@ -451,11 +426,11 @@ } return 3; case 0xD5: /* fixext 2 */ if (length < 4) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 2 count: 2]; @try { *object = createExtension(buffer[1], data); @@ -464,11 +439,11 @@ } return 4; case 0xD6: /* fixext 4 */ if (length < 6) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 2 count: 4]; @try { *object = createExtension(buffer[1], data); @@ -477,11 +452,11 @@ } return 6; case 0xD7: /* fixext 8 */ if (length < 10) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 2 count: 8]; @try { *object = createExtension(buffer[1], data); @@ -490,11 +465,11 @@ } return 10; case 0xD8: /* fixext 16 */ if (length < 18) - goto error; + @throw [OFTruncatedDataException exception]; data = [[OFData alloc] initWithItems: buffer + 2 count: 16]; @try { *object = createExtension(buffer[1], data); @@ -504,78 +479,76 @@ return 18; /* Strings */ case 0xD9: /* str 8 */ if (length < 2) - goto error; + @throw [OFTruncatedDataException exception]; count = buffer[1]; if (length < count + 2) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFString stringWithUTF8String: (const char *)buffer + 2 length: count]; return count + 2; case 0xDA: /* str 16 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; count = readUInt16(buffer + 1); if (length < count + 3) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFString stringWithUTF8String: (const char *)buffer + 3 length: count]; return count + 3; case 0xDB: /* str 32 */ if (length < 5) - goto error; + @throw [OFTruncatedDataException exception]; count = readUInt32(buffer + 1); if (length < count + 5) - goto error; + @throw [OFTruncatedDataException exception]; *object = [OFString stringWithUTF8String: (const char *)buffer + 5 length: count]; return count + 5; /* Arrays */ case 0xDC: /* array 16 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; return parseArray(buffer + 3, length - 3, object, readUInt16(buffer + 1), depthLimit) + 3; case 0xDD: /* array 32 */ if (length < 5) - goto error; + @throw [OFTruncatedDataException exception]; return parseArray(buffer + 5, length - 5, object, readUInt32(buffer + 1), depthLimit) + 5; /* Maps */ case 0xDE: /* map 16 */ if (length < 3) - goto error; + @throw [OFTruncatedDataException exception]; return parseTable(buffer + 3, length - 3, object, readUInt16(buffer + 1), depthLimit) + 3; case 0xDF: /* map 32 */ if (length < 5) - goto error; + @throw [OFTruncatedDataException exception]; return parseTable(buffer + 5, length - 5, object, readUInt32(buffer + 1), depthLimit) + 5; + default: + @throw [OFInvalidFormatException exception]; } - -error: - *object = nil; - return 0; } @implementation OFData (MessagePackValue) - (id)messagePackValue { @@ -586,16 +559,18 @@ { void *pool = objc_autoreleasePoolPush(); size_t count = [self count]; id object; - if (parseObject([self items], count, &object, depthLimit) != count || - object == nil) + if ([self itemSize] != 1) + @throw [OFInvalidArgumentException exception]; + + if (parseObject([self items], count, &object, depthLimit) != count) @throw [OFInvalidFormatException exception]; [object retain]; objc_autoreleasePoolPop(pool); return object; } @end Index: src/OFXMLParser.m ================================================================== --- src/OFXMLParser.m +++ src/OFXMLParser.m @@ -397,12 +397,11 @@ _state = OF_XMLPARSER_IN_EXCLAMATIONMARK; _acceptProlog = false; break; default: if (_depthLimit > 0 && [_previous count] >= _depthLimit) - @throw [OFMalformedXMLException - exceptionWithParser: self]; + @throw [OFOutOfRangeException exception]; _state = OF_XMLPARSER_IN_TAG_NAME; _acceptProlog = false; _i--; break;