From 2c2bfccccb022656e709532736a6bb5b9aade73e Mon Sep 17 00:00:00 2001 From: rfm Date: Tue, 28 Feb 2012 06:53:00 +0000 Subject: [PATCH] recommit with bugfix decoding array count git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34843 72102866-910b-0410-8b05-ffd578937521 --- Source/NSPortCoder.m | 94 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 9 deletions(-) diff --git a/Source/NSPortCoder.m b/Source/NSPortCoder.m index e5fc10c1a..0e02ccdaa 100644 --- a/Source/NSPortCoder.m +++ b/Source/NSPortCoder.m @@ -433,14 +433,47 @@ static IMP _xRefImp; /* Serialize a crossref. */ count: (NSUInteger)expected at: (void*)buf { - unsigned int i; - int offset = 0; - int size = objc_sizeof_type(type); + NSUInteger i; + NSUInteger offset = 0; + unsigned size = objc_sizeof_type(type); unsigned char info; - unsigned count; + NSUInteger count; (*_dTagImp)(_src, dTagSel, &info, 0, &_cursor); - (*_dDesImp)(_src, dDesSel, &count, @encode(unsigned), &_cursor, nil); + if (_version > 12401) + { + uint8_t c; + + /* Unpack variable length count. + */ + count = 0; + for (;;) + { + if (count * 128 < count) + { + [NSException raise: NSInternalInconsistencyException + format: @"overflow in array count"]; + } + count *= 128; + (*_dDesImp)(_src, dDesSel, &c, @encode(uint8_t), &_cursor, nil); + if (c & 128) + { + count += (c & 127); + } + else + { + count += c; + break; + } + } + } + else + { + unsigned c; + + (*_dDesImp)(_src, dDesSel, &c, @encode(unsigned), &_cursor, nil); + count = c; + } if (info != _GSC_ARY_B) { [NSException raise: NSInternalInconsistencyException @@ -1101,11 +1134,33 @@ static IMP _xRefImp; /* Serialize a crossref. */ count: (NSUInteger)count at: (const void*)buf { - unsigned i; - unsigned offset = 0; + NSUInteger i; + unsigned c = count; + uint8_t bytes[20]; + uint8_t *bytePtr = 0; + uint8_t byteCount = 0; + 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] > 12401) + { + 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; @@ -1133,7 +1188,18 @@ static IMP _xRefImp; /* Serialize a crossref. */ if (_initialPass == NO) { (*_eTagImp)(_dst, eTagSel, _GSC_ARY_B); - (*_eSerImp)(_dst, eSerSel, &count, @encode(unsigned), nil); + if (0 == byteCount) + { + (*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil); + } + else + { + for (i = 0; i < byteCount; i++) + { + (*_eSerImp) + (_dst, eSerSel, bytePtr + i, @encode(uint8_t), nil); + } + } } for (i = 0; i < count; i++) { @@ -1144,7 +1210,17 @@ static IMP _xRefImp; /* Serialize a crossref. */ else if (_initialPass == NO) { (*_eTagImp)(_dst, eTagSel, _GSC_ARY_B); - (*_eSerImp)(_dst, eSerSel, &count, @encode(unsigned), nil); + if (0 == byteCount) + { + (*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil); + } + else + { + for (i = 0; i < byteCount; i++) + { + (*_eSerImp)(_dst, eSerSel, bytePtr + i, @encode(uint8_t), nil); + } + } (*_eTagImp)(_dst, eTagSel, info); for (i = 0; i < count; i++)