Skip to content

Commit

Permalink
Implement dast enumeration mutation checks and add testcases for NSPo…
Browse files Browse the repository at this point in the history
…interArray
  • Loading branch information
rfm committed Jan 19, 2025
1 parent 39b1b7f commit c225efa
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 6 deletions.
22 changes: 21 additions & 1 deletion Source/NSPointerArray.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ @interface NSConcretePointerArray : NSPointerArray
void **_contents;
unsigned _capacity;
unsigned _grow_factor;
unsigned long _version;
}
@end

Expand Down Expand Up @@ -203,7 +204,7 @@ - (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState*)state
{
NSInteger count;

state->mutationsPtr = (unsigned long *)&state->mutationsPtr;
state->mutationsPtr = state->mutationsPtr;
count = MIN(len, [self count] - state->state);
if (count > 0)
{
Expand Down Expand Up @@ -312,6 +313,8 @@ - (void) compact
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
Expand All @@ -329,6 +332,7 @@ - (void) compact
}
}
_count = insert;
_version++;
}

- (id) copyWithZone: (NSZone*)zone
Expand All @@ -355,6 +359,16 @@ - (NSUInteger) count
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;
Expand Down Expand Up @@ -529,6 +543,7 @@ - (NSPointerFunctions*) pointerFunctions

- (void) removePointerAtIndex: (NSUInteger)index
{
_version++;
if (index >= _count)
{
[self _raiseRangeExceptionWithIndex: index from: _cmd];
Expand All @@ -539,22 +554,26 @@ - (void) removePointerAtIndex: (NSUInteger)index
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++;
}


#define ZEROING 0

- (void) setCount: (NSUInteger)count
{
_version++;
if (count > _count)
{
#if ZEROING
Expand Down Expand Up @@ -629,6 +648,7 @@ - (void) setCount: (NSUInteger)count
pointerFunctionsRelinquish(&_pf, &_contents[_count]);
}
}
_version++;
}

@end
Expand Down
33 changes: 28 additions & 5 deletions Tests/base/NSFastEnumeration/basic.m
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
#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"

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;
Expand Down Expand Up @@ -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;
}

0 comments on commit c225efa

Please sign in to comment.