Implement dast enumeration mutation checks and add testcases for NSPointerArray

This commit is contained in:
rfm 2025-01-19 08:42:12 +00:00
parent 39b1b7fd01
commit c225efa3ba
2 changed files with 49 additions and 6 deletions

View file

@ -44,6 +44,7 @@ static Class concreteClass = Nil;
void **_contents;
unsigned _capacity;
unsigned _grow_factor;
unsigned long _version;
}
@end
@ -203,7 +204,7 @@ static Class concreteClass = Nil;
{
NSInteger count;
state->mutationsPtr = (unsigned long *)&state->mutationsPtr;
state->mutationsPtr = state->mutationsPtr;
count = MIN(len, [self count] - state->state);
if (count > 0)
{
@ -312,6 +313,8 @@ static Class concreteClass = Nil;
NSUInteger insert = 0;
NSUInteger i;
_version++;
/* We can't use memmove here for __weak pointers, because that would omit the
* required read barriers. We could use objc_memmoveCollectable() for strong
* pointers, but we may as well use the same code path for everything
@ -329,6 +332,7 @@ static Class concreteClass = Nil;
}
}
_count = insert;
_version++;
}
- (id) copyWithZone: (NSZone*)zone
@ -355,6 +359,16 @@ static Class concreteClass = Nil;
return _count;
}
- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
objects: (__unsafe_unretained id[])stackbuf
count: (NSUInteger)len
{
state->mutationsPtr = &_version;
return [super countByEnumeratingWithState: state
objects: stackbuf
count: len];
}
- (void) dealloc
{
int i;
@ -529,6 +543,7 @@ static Class concreteClass = Nil;
- (void) removePointerAtIndex: (NSUInteger)index
{
_version++;
if (index >= _count)
{
[self _raiseRangeExceptionWithIndex: index from: _cmd];
@ -539,15 +554,18 @@ static Class concreteClass = Nil;
pointerFunctionsMove(&_pf, &_contents[index-1], &_contents[index]);
}
_contents[--_count] = NULL;
_version++;
}
- (void) replacePointerAtIndex: (NSUInteger)index withPointer: (void*)item
{
_version++;
if (index >= _count)
{
[self _raiseRangeExceptionWithIndex: index from: _cmd];
}
pointerFunctionsReplace(&_pf, &_contents[index], item);
_version++;
}
@ -555,6 +573,7 @@ static Class concreteClass = Nil;
- (void) setCount: (NSUInteger)count
{
_version++;
if (count > _count)
{
#if ZEROING
@ -629,6 +648,7 @@ static Class concreteClass = Nil;
pointerFunctionsRelinquish(&_pf, &_contents[_count]);
}
}
_version++;
}
@end

View file

@ -1,8 +1,4 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSOrderedSet.h>
#import <Foundation/Foundation.h>
#import "ObjectTesting.h"
#import "../../../Source/GSFastEnumeration.h"
@ -10,6 +6,25 @@ static SEL add;
static SEL set;
static SEL key;
@implementation NSPointerArray (TestHelpers)
- (void) addObject: (id)anObject
{
[self addPointer: anObject];
}
- (void) removeObject: (id)anObject
{
int i = [self count];
while (i-- > 0)
{
if ([self pointerAtIndex: i] == (void*)anObject)
{
[self removePointerAtIndex: i];
}
}
}
@end
void fast_enumeration_mutation_add(id mutableCollection)
{
NSUInteger i = 0;
@ -139,6 +154,14 @@ int main()
test_fast_enumeration(table, objects);
END_SET("NSHashTable")
START_SET("NSPointerArray")
id array = [NSPointerArray weakObjectsPointerArray];
FOR_IN(id, o, objects)
[array addPointer: o];
END_FOR_IN(objects)
test_fast_enumeration(array, objects);
END_SET("NSPointerArray")
[arp release]; arp = nil;
return 0;
}