diff --git a/ChangeLog b/ChangeLog index 4dbe87697..67cf2ec21 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2002-02-21 Richard Frith-Macdonald + + * Source/NSValue.m: Fixed bug in archiving NSValue objects ... was + creating faulty archives which would crash on unarchiving. + If you have any archives created using the buggy code, try to + unarchive them by using the previous version of this file but + with the RELEASE() of the decoded NSData object removed. This + *might* permit archive recovery, though it will cause a memory leak. + 2002-02-20 Richard Frith-Macdonald * Source/NSUser.m: locking erro fixed by Stephen brandon diff --git a/Source/NSValue.m b/Source/NSValue.m index 5181f24f3..1b16ffb68 100644 --- a/Source/NSValue.m +++ b/Source/NSValue.m @@ -366,7 +366,7 @@ static NSLock *placeholderLock; - (void) encodeWithCoder: (NSCoder *)coder { unsigned size; - char *data; + const char *data; const char *objctype = [self objCType]; NSMutableData *d; @@ -378,10 +378,15 @@ static NSLock *placeholderLock; [self getValue: (void*)data]; d = [NSMutableData new]; [d serializeDataAt: data ofObjCType: objctype context: nil]; - [coder encodeValueOfObjCType: @encode(id) at: &d]; + size = [d length]; + [coder encodeValueOfObjCType: @encode(unsigned) at: &size]; + NSZoneFree(NSDefaultMallocZone(), (void*)data); + data = [d bytes]; + [coder encodeArrayOfObjCType: @encode(unsigned char) count: size at: data]; RELEASE(d); - NSZoneFree(NSDefaultMallocZone(), data); } + +@class NSDataStatic; // Neede for decoding. - (id) initWithCoder: (NSCoder *)coder { @@ -458,9 +463,13 @@ static NSLock *placeholderLock; } else { - NSData *d; + static NSData *d = nil; unsigned cursor = 0; + if (d == nil) + { + d = [NSDataStatic allocWithZone: NSDefaultMallocZone()]; + } /* * For performance, decode small values directly onto the stack, * For larger values we allocate and deallocate heap space. @@ -470,26 +479,42 @@ static NSLock *placeholderLock; { unsigned char data[size]; - [coder decodeValueOfObjCType: @encode(id) at: &d]; - [d deserializeDataAt: data - ofObjCType: objctype - atCursor: &cursor - context: nil]; + [coder decodeValueOfObjCType: @encode(unsigned) at: &size]; + { + unsigned char serialized[size]; + + [coder decodeArrayOfObjCType: @encode(unsigned char) + count: size + at: (void*)serialized]; + d = [d initWithBytesNoCopy: (void*)serialized length: size]; + [d deserializeDataAt: data + ofObjCType: objctype + atCursor: &cursor + context: nil]; + } o = [o initWithBytes: data objCType: objctype]; - RELEASE(d); } else { - unsigned char *data; + void *data; data = (void *)NSZoneMalloc(NSDefaultMallocZone(), size); - [coder decodeValueOfObjCType: @encode(id) at: &d]; - [d deserializeDataAt: data - ofObjCType: objctype - atCursor: &cursor - context: nil]; + [coder decodeValueOfObjCType: @encode(unsigned) at: &size]; + { + void *serialized; + + serialized = (void *)NSZoneMalloc(NSDefaultMallocZone(), size); + [coder decodeArrayOfObjCType: @encode(unsigned char) + count: size + at: serialized]; + d = [d initWithBytesNoCopy: serialized length: size]; + [d deserializeDataAt: data + ofObjCType: objctype + atCursor: &cursor + context: nil]; + NSZoneFree(NSDefaultMallocZone(), serialized); + } o = [o initWithBytes: data objCType: objctype]; - RELEASE(d); NSZoneFree(NSDefaultMallocZone(), data); } }