Attempt to sort out versioning of archives/DO to be more tolerant/flexible.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35118 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2012-04-27 11:58:56 +00:00
parent 6ebcdc0883
commit f224e6286b
6 changed files with 189 additions and 48 deletions

View file

@ -1,3 +1,22 @@
2012-02-28 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSArchiver.m:
* Source/NSUnarchiver.m:
* Source/NSPortCoder.m:
* Source/Coder.m:
Updates to cope with the fact that some BSD ports of gnustep-base
used incorrect versioning, and that people have released Gorm
files with versioning incompatible with current releases.
1. dissociate coder -systemVersion from the actual system version,
so that if people mess with the gnustep-base version, their
non-standard releases will still interoperate with normal code.
2. Implement new array encoding/decoding compatible with earlier
versions (except if the array contains exactly 0xffffffff items).
3. Raise exception if decoding archives with an unsupported version.
4. Add GSCoderSystemVersion user default to override the system
version used for encoding ... for testing and tweaking to generate
archives in, or communicate with DO servers using an earlier version.
2012-04-23 Fred Kiefer <FredKiefer@gmx.de>
* Tests/base/NSAutoreleasePool/autorelease_eh.m:
@ -6,11 +25,11 @@
2012-04-23 12:47 theraven
* libs/base/trunk/Source/NSAutoreleasePool.m,
libs/base/trunk/Tests/base/NSAutoreleasePool/autorelease_eh.m:
Fix a bug in the new autorelease pool implementation when pools
are destroyed in the wrong order.
libs/base/trunk/Tests/base/NSAutoreleasePool/autorelease_eh.m:
Fix a bug in the new autorelease pool implementation when pools
are destroyed in the wrong order.
Test cast by Chris Armstrong!
Test cast by Chris Armstrong!
2012-04-22 Riccardo Mottola <rm@gnu.org>

View file

@ -254,20 +254,17 @@ static Class NSMutableDataMallocClass;
count: (NSUInteger)count
at: (const void*)buf
{
unsigned c = count;
uint32_t c;
uint8_t bytes[20];
uint8_t *bytePtr = 0;
uint8_t byteCount = 0;
NSUInteger i;
NSUInteger offset = 0;
unsigned size = objc_sizeof_type(type);
uint32_t size = objc_sizeof_type(type);
uint32_t version = [self systemVersion];
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)
if (12402 == version)
{
NSUInteger tmp = count;
@ -280,6 +277,21 @@ static Class NSMutableDataMallocClass;
}
bytePtr = &bytes[sizeof(bytes) - byteCount];
}
else
{
/* We normally store the count as a 32bit integer ... but if it's
* very big, we store 0xffffffff and then an additional 64bit value
* containing the actual count.
*/
if (count >= 0xffffffff)
{
c = 0xffffffff;
}
else
{
c = count;
}
}
switch (*type)
{
@ -308,17 +320,21 @@ static Class NSMutableDataMallocClass;
if (_initialPass == NO)
{
(*_tagImp)(_dst, tagSel, _GSC_ARY_B);
if (0 == byteCount)
{
(*_serImp)(_dst, serSel, &c, @encode(unsigned), nil);
}
else
if (12402 == version)
{
for (i = 0; i < byteCount; i++)
{
(*_serImp)(_dst, serSel, bytePtr + i, @encode(uint8_t), nil);
}
}
else
{
(*_serImp)(_dst, serSel, &c, @encode(uint32_t), nil);
if (0xffffffff == c)
{
(*_serImp)(_dst, serSel, &count, @encode(NSUInteger), nil);
}
}
}
for (i = 0; i < c; i++)
@ -330,17 +346,21 @@ static Class NSMutableDataMallocClass;
else if (_initialPass == NO)
{
(*_tagImp)(_dst, tagSel, _GSC_ARY_B);
if (0 == byteCount)
{
(*_serImp)(_dst, serSel, &c, @encode(unsigned), nil);
}
else
if (12402 == version)
{
for (i = 0; i < byteCount; i++)
{
(*_serImp)(_dst, serSel, bytePtr + i, @encode(uint8_t), nil);
}
}
else
{
(*_serImp)(_dst, serSel, &c, @encode(uint32_t), nil);
if (0xffffffff == c)
{
(*_serImp)(_dst, serSel, &count, @encode(NSUInteger), nil);
}
}
(*_tagImp)(_dst, tagSel, info);
for (i = 0; i < count; i++)

View file

@ -36,14 +36,42 @@
#import "Foundation/NSData.h"
#import "Foundation/NSCoder.h"
#import "Foundation/NSSerialization.h"
#import "Foundation/NSUserDefaults.h"
#import "GNUstepBase/NSObject+GNUstepBase.h"
@implementation NSCoder
/* We used to use a system version which actually reflected the version
* of GNUstep-base ... but people screwed that up by releasing versions
* of base with unofficial version numbers conflicting with the scheme.
* So ... we are now starting from a basepoint of 1 million ... on the
* basis that the old numbering scheme derived from the gnustep-base
* major.minor.subminor versioning (in which each can range from 0 to 99)
* should not have allowed anyone to create an archive with a version
* greater than 999999.
* In future, the system version will change if (and only if) the format
* of the encoded data changes.
*/
#define MAX_SUPPORTED_SYSTEM_VERSION 1000000
static unsigned systemVersion = MAX_SUPPORTED_SYSTEM_VERSION;
+ (void) initialize
{
if (self == [NSCoder class])
{
unsigned sv;
/* The GSCoderSystemVersion user default is provided for testing
* and to allow new code to communicate (via Distributed Objects)
* with systems running older versions.
*/
sv = [[NSUserDefaults standardUserDefaults]
integerForKey: @"GSCoderSystemVersion"];
if (sv > 0 && sv <= MAX_SUPPORTED_SYSTEM_VERSION)
{
systemVersion = sv;
}
}
}
@ -298,8 +326,7 @@
- (unsigned) systemVersion
{
return (((GNUSTEP_BASE_MAJOR_VERSION * 100)
+ GNUSTEP_BASE_MINOR_VERSION) * 100) + GNUSTEP_BASE_SUBMINOR_VERSION;
return systemVersion;
}

View file

@ -351,10 +351,16 @@ static IMP _eSerImp; /* Method to serialize with. */
static IMP _eTagImp; /* Serialize a type tag. */
static IMP _xRefImp; /* Serialize a crossref. */
static unsigned encodingVersion;
+ (void) initialize
{
if (self == [NSPortCoder class])
{
NSCoder *coder = [NSCoder new];
encodingVersion = [coder systemVersion];
[coder release];
#if GS_WITH_GC
/* We create a typed memory descriptor for map nodes.
*/
@ -435,12 +441,12 @@ static IMP _xRefImp; /* Serialize a crossref. */
{
NSUInteger i;
NSUInteger offset = 0;
unsigned size = objc_sizeof_type(type);
uint32_t size = objc_sizeof_type(type);
unsigned char info;
NSUInteger count;
(*_dTagImp)(_src, dTagSel, &info, 0, &_cursor);
if (_version > 12401)
if (12402 == _version)
{
uint8_t c;
@ -469,10 +475,15 @@ static IMP _xRefImp; /* Serialize a crossref. */
}
else
{
unsigned c;
uint32_t c;
(*_dDesImp)(_src, dDesSel, &c, @encode(unsigned), &_cursor, nil);
(*_dDesImp)(_src, dDesSel, &c, @encode(uint32_t), &_cursor, nil);
count = c;
if (0xffffffff == c)
{
(*_dDesImp)(_src, dDesSel,
&count, @encode(NSUInteger), &_cursor, nil);
}
}
if (info != _GSC_ARY_B)
{
@ -1135,19 +1146,16 @@ static IMP _xRefImp; /* Serialize a crossref. */
at: (const void*)buf
{
NSUInteger i;
unsigned c = count;
uint32_t c = count;
uint8_t bytes[20];
uint8_t *bytePtr = 0;
uint8_t byteCount = 0;
NSUInteger offset = 0;
unsigned size = objc_sizeof_type(type);
uint32_t size = objc_sizeof_type(type);
uint32_t version = [self systemVersion];
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)
if (12402 == version)
{
NSUInteger tmp = count;
@ -1160,6 +1168,21 @@ static IMP _xRefImp; /* Serialize a crossref. */
}
bytePtr = &bytes[sizeof(bytes) - byteCount];
}
else
{
/* We normally store the count as a 32bit integer ... but if it's
* very big, we store 0xffffffff and then an additional 64bit value
* containing the actual count.
*/
if (count >= 0xffffffff)
{
c = 0xffffffff;
}
else
{
c = count;
}
}
switch (*type)
{
@ -1188,11 +1211,7 @@ static IMP _xRefImp; /* Serialize a crossref. */
if (_initialPass == NO)
{
(*_eTagImp)(_dst, eTagSel, _GSC_ARY_B);
if (0 == byteCount)
{
(*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil);
}
else
if (12402 == version)
{
for (i = 0; i < byteCount; i++)
{
@ -1200,6 +1219,14 @@ static IMP _xRefImp; /* Serialize a crossref. */
(_dst, eSerSel, bytePtr + i, @encode(uint8_t), nil);
}
}
else
{
(*_eSerImp)(_dst, eSerSel, &c, @encode(uint32_t), nil);
if (0xffffffff == c)
{
(*_eSerImp)(_dst, eSerSel, &count, @encode(NSUInteger), nil);
}
}
}
for (i = 0; i < count; i++)
{
@ -1210,17 +1237,21 @@ static IMP _xRefImp; /* Serialize a crossref. */
else if (_initialPass == NO)
{
(*_eTagImp)(_dst, eTagSel, _GSC_ARY_B);
if (0 == byteCount)
{
(*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil);
}
else
if (12402 == version)
{
for (i = 0; i < byteCount; i++)
{
(*_eSerImp)(_dst, eSerSel, bytePtr + i, @encode(uint8_t), nil);
}
}
else
{
(*_eSerImp)(_dst, eSerSel, &c, @encode(unsigned), nil);
if (0xffffffff == c)
{
(*_eSerImp)(_dst, eSerSel, &count, @encode(NSUInteger), nil);
}
}
(*_eTagImp)(_dst, eTagSel, info);
for (i = 0; i < count; i++)
@ -1920,6 +1951,12 @@ static IMP _xRefImp; /* Serialize a crossref. */
objects: &sizeO
pointers: &sizeP];
if (_version > encodingVersion)
{
[NSException raise: NSInvalidArgumentException
format: @"Message systemVersion (%u) not recognised", _version];
}
/*
* Allocate and initialise arrays to build crossref maps in.
*/

View file

@ -398,16 +398,22 @@ mapClassName(NSUnarchiverObjectInfo *info)
@implementation NSUnarchiver
static Class NSDataMallocClass;
static unsigned encodingVersion;
+ (void) initialize
{
if ([self class] == [NSUnarchiver class])
{
NSArchiver *archiver = [NSArchiver new];
encodingVersion = [archiver systemVersion];
[archiver release];
desSel = @selector(deserializeDataAt:ofObjCType:atCursor:context:);
tagSel = @selector(deserializeTypeTag:andCrossRef:atCursor:);
dValSel = @selector(decodeValueOfObjCType:at:);
clsDict = [[NSMutableDictionary alloc] initWithCapacity: 200];
NSDataMallocClass = [NSDataMalloc class];
}
}
@ -536,7 +542,7 @@ static Class NSDataMallocClass;
NSUInteger count;
(*tagImp)(src, tagSel, &info, 0, &cursor);
if ([self systemVersion] > 12401)
if ([self systemVersion] == 12402)
{
uint8_t c;
@ -565,10 +571,14 @@ static Class NSDataMallocClass;
}
else
{
unsigned c;
uint32_t c;
(*desImp)(src, desSel, &c, @encode(unsigned), &cursor, nil);
(*desImp)(src, desSel, &c, @encode(uint32_t), &cursor, nil);
count = c;
if (0xffffffff == c)
{
(*desImp)(src, desSel, &count, @encode(NSUInteger), &cursor, nil);
}
}
if (info != _GSC_ARY_B)
{
@ -1524,6 +1534,11 @@ static Class NSDataMallocClass;
classes: &sizeC
objects: &sizeO
pointers: &sizeP];
if (version > encodingVersion)
{
[NSException raise: NSInvalidArgumentException
format: @"Archive systemVersion (%u) not recognised", version];
}
if (clsMap == 0)
{

View file

@ -4,13 +4,36 @@
* might be from an earlier build.
*/
// disable extensions ... we want to use standard code
/* disable extensions ... we want to use standard code
*/
#ifdef _GNU_SOURCE
#undef _GNU_SOURCE
#endif
/* Ensure we have _XOPEN_SOURCE turned on at the appropriate
* level for the facilities we need.
*
* Minimum of 600 for string.h so we get the POSIX strerror_r() behavior
*/
#if defined(_XOPEN_SOURCE)
#if _XOPEN_SOURCE < 600
#undef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#else
#define _XOPEN_SOURCE 600
#endif
#import "config.h"
#if defined(HAVE_STRING_H)
/* For POSIX strerror_r()
*/
#include <string.h>
#endif
#include <errno.h>
/* If this is included in a file in the Additions subdirectory, and we are
* building for use with the NeXT/Apple Foundation, then we need to import
* the native headers in preference to any of our own.