From 3aee9ca4bae17d6b255549c66b75ecf9fb3d74d0 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 27 Feb 2012 20:07:05 +0000 Subject: [PATCH] revise archive format. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34832 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 9 +++++++ Source/NSArchiver.m | 58 +++++++++++++++++++++++++++++++++++++------ Source/NSUnarchiver.m | 38 ++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7856ca9c3..9c561f6be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-02-28 Richard Frith-Macdonald + + * Source/NSArchiver.m: + * Source/NSUnarchiver.m: + Revise archive format to allow for variable sized array counts ... + original versionallowed for variable encodings of integral types in + archived data, but not for the count of the nuymber of items in the + array :-( + 2012-02-27 Fred Kiefer * Source/NSXMLNode.m (-copyWithZone:): Copy name spaces as well. diff --git a/Source/NSArchiver.m b/Source/NSArchiver.m index b74a56f55..e017512d3 100644 --- a/Source/NSArchiver.m +++ b/Source/NSArchiver.m @@ -254,12 +254,33 @@ static Class NSMutableDataMallocClass; count: (NSUInteger)count at: (const void*)buf { - NSUInteger c = count; + unsigned c = count; + uint8_t bytes[20]; + uint8_t *bytePtr = 0; + uint8_t byteCount = 0; NSUInteger i; NSUInteger offset = 0; unsigned size = objc_sizeof_type(type); uchar info; + /* The array count is encoded as a sequence of bytes containing 7bits of + * data and using the eighth (top) bit to indicate that there are more + * bytes in the sequence. + */ + if ([self systemVersion] >= ((((1 * 100) + 24) * 100) + 1)) + { + NSUInteger tmp = count; + + bytes[sizeof(bytes) - ++byteCount] = (uint8_t)(tmp % 128); + tmp /= 128; + while (tmp > 0) + { + bytes[sizeof(bytes) - ++byteCount] = (uint8_t)(128 | (tmp % 128)); + tmp /= 128; + } + bytePtr = &bytes[sizeof(bytes) - byteCount]; + } + switch (*type) { case _C_ID: info = _GSC_NONE; break; @@ -287,8 +308,20 @@ static Class NSMutableDataMallocClass; if (_initialPass == NO) { (*_tagImp)(_dst, tagSel, _GSC_ARY_B); - (*_serImp)(_dst, serSel, &c, @encode(NSUInteger), nil); + if (0 == byteCount) + { + (*_serImp)(_dst, serSel, &c, @encode(unsigned), nil); + } + else + { + i = byteCount; + for (i = 0; i < byteCount; i++) + { + (*_serImp)(_dst, serSel, bytePtr + i, @encode(uint8_t), nil); + } + } } + for (i = 0; i < c; i++) { (*_eValImp)(self, eValSel, type, (char*)buf + offset); @@ -298,10 +331,21 @@ static Class NSMutableDataMallocClass; else if (_initialPass == NO) { (*_tagImp)(_dst, tagSel, _GSC_ARY_B); - (*_serImp)(_dst, serSel, &c, @encode(NSUInteger), nil); + if (0 == byteCount) + { + (*_serImp)(_dst, serSel, &c, @encode(unsigned), nil); + } + else + { + i = byteCount; + for (i = 0; i < byteCount; i++) + { + (*_serImp)(_dst, serSel, bytePtr + i, @encode(uint8_t), nil); + } + } (*_tagImp)(_dst, tagSel, info); - for (i = 0; i < c; i++) + for (i = 0; i < count; i++) { (*_serImp)(_dst, serSel, (char*)buf + offset, type, nil); offset += size; @@ -320,7 +364,7 @@ static Class NSMutableDataMallocClass; case _C_ARY_B: { - NSUInteger count = atoll(++type); + unsigned count = atoi(++type); while (isdigit(*type)) { @@ -734,9 +778,9 @@ static Class NSMutableDataMallocClass; - (void) encodeDataObject: (NSData*)anObject { - NSUInteger l = [anObject length]; + unsigned l = [anObject length]; - (*_eValImp)(self, eValSel, @encode(NSUInteger), &l); + (*_eValImp)(self, eValSel, @encode(unsigned int), &l); if (l) { const void *b = [anObject bytes]; diff --git a/Source/NSUnarchiver.m b/Source/NSUnarchiver.m index 78742eeca..45a1b4f2c 100644 --- a/Source/NSUnarchiver.m +++ b/Source/NSUnarchiver.m @@ -531,12 +531,40 @@ static Class NSDataMallocClass; { NSUInteger i; NSUInteger offset = 0; - NSUInteger size = (unsigned int)objc_sizeof_type(type); + unsigned int size = (unsigned int)objc_sizeof_type(type); unsigned char info; NSUInteger count; (*tagImp)(src, tagSel, &info, 0, &cursor); - (*desImp)(src, desSel, &count, @encode(NSUInteger), &cursor, nil); + if ([self systemVersion] >= ((((1 * 100) + 24) * 100) + 1)) + { + uint8_t c; + + /* Unpack variable length count. + */ + count = 0; + for (;;) + { + count *= 128; + (*desImp)(src, desSel, &c, @encode(uint8_t), &cursor, nil); + if (c & 128) + { + count += (c & 127); + } + else + { + count += c; + break; + } + } + } + else + { + unsigned c; + + (*desImp)(src, desSel, &c, @encode(unsigned), &cursor, nil); + count = c; + } if (info != _GSC_ARY_B) { [NSException raise: NSInternalInconsistencyException @@ -545,7 +573,7 @@ static Class NSDataMallocClass; if (count != expected) { [NSException raise: NSInternalInconsistencyException - format: @"expected array count %"PRIuPTR" and got %"PRIuPTR, + format: @"expected array count %u and got %u", expected, count]; } @@ -1219,9 +1247,9 @@ static Class NSDataMallocClass; - (NSData*) decodeDataObject { - NSUInteger l; + unsigned l; - (*dValImp)(self, dValSel, @encode(NSUInteger), &l); + (*dValImp)(self, dValSel, @encode(unsigned int), &l); if (l) { unsigned char c;