From 314a609fe899ba11801b2b00d5990f54c190c7fb Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 30 Dec 2024 12:56:44 +0000 Subject: [PATCH 1/4] Use fprintf rather than NSLog to record object ownership tracking with minimal dependencies on any classes. --- Source/Additions/NSObject+GNUstepBase.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index 05753a705..590e6a473 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -541,8 +541,8 @@ + (BOOL) shouldCleanUp } GS_MUTEX_UNLOCK(trackLock); fprintf(stderr, "Tracking ownership - unable to find entry for" - " instance %p of '%s'\n", o, class_getName(c)); - NSLog(@"Tracking ownership %p problem at %s", + " instance %p of '%s'.\n", o, class_getName(c)); + fprintf(stderr, "Tracking ownership %p problem at %s.\n", o, stackTrace(1)); /* Should never happen because we don't remove class entries, but I suppose @@ -598,7 +598,7 @@ - (void) _replacementDealloc } } GS_MUTEX_UNLOCK(trackLock); - NSLog(@"Tracking ownership -[%p dealloc] at %s", + fprintf(stderr, "Tracking ownership -[%p dealloc] at %s.\n", self, stackTrace(2)); (*dealloc)(self, _cmd); } @@ -620,7 +620,7 @@ - (void) _replacementRelease unsigned rc; rc = (unsigned)[self retainCount]; - NSLog(@"Tracking ownership -[%p release] %u->%u at %s", + fprintf(stderr, "Tracking ownership -[%p release] %u->%u at %s.\n", self, rc, rc-1, stackTrace(2)); (*release)(self, _cmd); } @@ -644,7 +644,7 @@ - (id) _replacementRetain rc = (unsigned)[self retainCount]; result = (*retain)(self, _cmd); - NSLog(@"Tracking ownership -[%p retain] %u->%u at %s", + fprintf(stderr, "Tracking ownership -[%p retain] %u->%u at %s.\n", self, rc, (unsigned)[self retainCount], stackTrace(2)); } return result; @@ -755,7 +755,7 @@ + (void) trackOwnership l->next = tracked; tracked = l; GS_MUTEX_UNLOCK(trackLock); - NSLog(@"Tracking ownership started for class %p at %s", + fprintf(stderr, "Tracking ownership started for class %p at %s.\n", self, stackTrace(1)); } @@ -823,7 +823,7 @@ - (void) trackOwnership li->next = tracked; tracked = li; GS_MUTEX_UNLOCK(trackLock); - NSLog(@"Tracking ownership started for instance %p at %s", + fprintf(stderr, "Tracking ownership started for instance %p at %s.\n", self, stackTrace(1)); } From 9e86902ba137031ea5e7826753b69547c52e3afc Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 30 Dec 2024 12:57:59 +0000 Subject: [PATCH 2/4] Alter initialisation order to make plist generation more robust. --- Source/NSPropertyList.m | 61 ++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/Source/NSPropertyList.m b/Source/NSPropertyList.m index 43b31cfcb..3d418d92e 100644 --- a/Source/NSPropertyList.m +++ b/Source/NSPropertyList.m @@ -2379,30 +2379,46 @@ @implementation NSPropertyListSerialization + (void) initialize { - if (classInitialized == NO) - { - NSMutableCharacterSet *s; + NSMutableCharacterSet *s; - classInitialized = YES; - - NSStringClass = [NSString class]; - NSMutableStringClass = [NSMutableString class]; - NSDataClass = [NSData class]; - NSDateClass = [NSDate class]; - NSNumberClass = [NSNumber class]; - NSArrayClass = [NSArray class]; - NSDictionaryClass = [NSDictionary class]; - GSStringClass = [GSString class]; - GSMutableStringClass = [GSMutableString class]; + if (Nil == NSStringClass) NSStringClass = [NSString class]; + if (Nil == GSStringClass) GSStringClass = [GSString class]; + if (Nil == NSMutableStringClass) + NSMutableStringClass = [NSMutableString class]; + if (Nil == GSMutableStringClass) + GSMutableStringClass = [GSMutableString class]; + if (Nil == NSArrayClass) NSArrayClass = [NSArray class]; + if (Nil == plArray) + { plArray = [GSMutableArray class]; plAdd = (id (*)(id, SEL, id)) [plArray instanceMethodForSelector: @selector(addObject:)]; + } + if (Nil == NSDictionaryClass) NSDictionaryClass = [NSDictionary class]; + if (Nil == plDictionary) + { plDictionary = [GSMutableDictionary class]; plSet = (id (*)(id, SEL, id, id)) [plDictionary instanceMethodForSelector: @selector(setObject:forKey:)]; + } + + if (Nil == NSDataClass) NSDataClass = [NSData class]; + if (Nil == NSNumberClass) NSNumberClass = [NSNumber class]; + if (nil == boolN) + { + boolN = [[NSNumber numberWithBool: NO] retain]; + [[NSObject leakAt: &boolN] release]; + } + if (nil == boolY) + { + boolY = [[NSNumber numberWithBool: YES] retain]; + [[NSObject leakAt: &boolY] release]; + } + if (nil == oldQuotables) + { /* The '$', '.', '/' and '_' characters used to be OK to use in * property lists, but OSX now quotes them, so we follow suite. */ @@ -2413,7 +2429,10 @@ + (void) initialize [s invert]; oldQuotables = s; [[NSObject leakAt: &oldQuotables] release]; + } + if (nil == xmlQuotables) + { s = [NSMutableCharacterSet new]; [s addCharactersInString: @"&<>'\\\""]; [s addCharactersInRange: NSMakeRange(0x0001, 0x001f)]; @@ -2423,13 +2442,17 @@ + (void) initialize [s addCharactersInRange: NSMakeRange(0xFFFE, 0x0002)]; xmlQuotables = s; [[NSObject leakAt: &xmlQuotables] release]; + } - boolN = [[NSNumber numberWithBool: NO] retain]; - [[NSObject leakAt: &boolN] release]; - - boolY = [[NSNumber numberWithBool: YES] retain]; - [[NSObject leakAt: &boolY] release]; + /* Initialize the date class last as it has external dependencies on + * time zone data. + */ + if (Nil == NSDateClass) + { + NSDateClass = [NSDate class]; } + + classInitialized = YES; } + (NSData*) dataFromPropertyList: (id)aPropertyList From 0d66ee0f82caf5bd8c6be87aaf0c5ac2e43dad21 Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 30 Dec 2024 12:59:20 +0000 Subject: [PATCH 3/4] Fix false positive in leak analysis due to clearing pointer at exit --- Source/NSTimeZone.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index b509a9c78..6eea6fd01 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -1288,7 +1288,6 @@ + (void) atExit GS_MUTEX_UNLOCK(zone_mutex); DESTROY(zoneDictionary); - DESTROY(localTimeZone); DESTROY(defaultTimeZone); DESTROY(systemTimeZone); DESTROY(abbreviationDictionary); @@ -1346,6 +1345,10 @@ + (void) initialize absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); + /* NB. the instance of NSLocalTimeZone overrides memory management + * so it is never deallocated. This must not be destroyed in the + * +atExit: method becuse that would confuse leak analysis tools. + */ localTimeZone = [[NSLocalTimeZone alloc] init]; [[NSNotificationCenter defaultCenter] addObserver: self From 970e5a32c4504a8ac55ea676140a81782e17044a Mon Sep 17 00:00:00 2001 From: rfm Date: Mon, 30 Dec 2024 13:00:21 +0000 Subject: [PATCH 4/4] fix truncated region information --- NSTimeZones/NSTimeZones.tar | Bin 952320 -> 962560 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/NSTimeZones/NSTimeZones.tar b/NSTimeZones/NSTimeZones.tar index 2e0df8bb749d1e3416da6054453224a308863569..6633d5cd0a2c2416ffbb501e9f06f0f538954de0 100644 GIT binary patch delta 31564 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 delta 22390 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 XCjS0#(c7D=|EPYjk<<@PIam2Vp({t0