discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Crash in countByEnumeratingWithState method of GNUstep's implementat


From: Richard Frith-Macdonald
Subject: Re: Crash in countByEnumeratingWithState method of GNUstep's implementation of NSArray
Date: Wed, 8 Jan 2014 13:02:09 +0000

On 8 Jan 2014, at 12:34, Mathias Bauer <mathias_bauer@gmx.net> wrote:

> I doubt that returning the address of a stack variable will fix that. "size" 
> must become an iVar, IMHO.
> 
> Regards,
> Mathias
> 
> Am 08.01.14 13:21, schrieb Quentin Mathé:
>> Hi Matthias,
>> 
>> Le 8 janv. 2014 à 10:45, Mathias Bauer a écrit :
>> 
>>> Hi,
>>> 
>>> it seems that the implementation of countByEnumeratingWithState in NSArray 
>>> is broken.
>>> 
>>> The following code in NSArray.m
>>> 
>>>> {
>>>>   NSUInteger size = [self count];
>>>>   NSInteger count;
>>>> 
>>>>   /* This is cached in the caller at the start and compared at each
>>>>    * iteration.   If it changes during the iteration then
>>>>    * objc_enumerationMutation() will be called, throwing an exception.
>>>>    */
>>>>   state->mutationsPtr = (unsigned long *)size;
>>> 
>>> of course crashes as soon as any fast enumeration is executed for any 
>>> collection deriving from NSArray. The cast in the last line can't work.
>>> 
>>> Now I'm wondering how this problem could remain undiscovered or at least 
>>> unfixed for such a long time. I doubt that everybody who implemented a 
>>> class that derives from NSArray also re-implemented this method.
>> 
>> I just stumbled on it today while testing some custom NSArray subclass. I 
>> think most people don't write NSArray subclass, and GNUstep concrete 
>> subclasses are all overriding the fast enumeration method, so the default 
>> fast enumeration implementation in NSArray was just never executed.
>> 
>>> A simple fix would be to add an iVar that gets the result of [self count] 
>>> each time this method is called and assigning its address to 
>>> state->mutationsPtr.
>> 
>> The following should be enough to fix it: state->mutationsPtr = (unsigned 
>> long *)&size;
>> 
>>> Any chance for getting this fixed in the trunk version?
>> 
>> I'll commit this fix today.

I don't use fast enumeration, so I'm unfamiliar with this, but on the basis of 
looking at this code and reading a little it also seems strange to me to use a 
stack variable, unless you can somehow guarantee the stack will be left intact 
while the fast enumeration takes place?

I wonder if the pointer should simply be set to self?  That would presumably 
point to something guaranteed to exist for the duration fo the enumeration and 
presumably to remain unchanged.  This ought to be fine for NSArray which is 
never mutated.

I don't understand the point of using an ivar though.  Leaving aside the fact 
that NSArray is an abstract class and is not supposed/allowed to have ivars, 
what would be the point? As I understand it the pointer is supposed to be set 
to point to some value which will change if the collection is mutated ... that 
should never happen for NSArray and if someone implements an NSMutableArray 
subclass they would presumably want to implement their own storage and 
mechanism to indicate when their contents had changed.  So it looks to me like 
subclasses of NSMutableArray ought to be implementing their own version of this 
method.

Of course, you may know better ... have Apple added an API to NSMutableArray 
which allows a subclass to mark instances of itsself as mutated?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]