Changeset 17

Show
Ignore:
Timestamp:
09/12/07 11:03:54 AM (10 months ago)
Author:
aaron
Message:
  • incorporated patch described below

From: <hidden>
To: <me>
Subject: CocoaICU issues
Date: Tue, 11 Sep 2007 10:59:24 -07

I just found CocoaICU yesterday and have started looking at it. I've found one significant issue and two minor ones.

Unicode string buffers aren't being retained properly. -[ICUPattern setTextToSearch:] points its instance variable textToSearch to the input UChar*, without copying the string. The
comment reads "retained by the NSString"; however, this isn't true. The string buffer is the result of -[NSString cStringUsingEncoding:], which returns an autoreleased buffer that
will be freed when the nearest autorelease pool goes out of scope.
The effect is that if some code created a pattern object and set a search string, then returned to its caller and later (like after another user event) tried to use the pattern, it
would probably get garbage results or crash, because the search string pointed to a freed block of memory.
Instead, you should malloc your own buffer, then call -getCharacters: on the string to copy them into that buffer.

Flags in ICUPattern.h are not "const". The types of CaseInsensitiveMatching?, etc. should be "const unsigned", not "unsigned", otherwise the values could be accidentally modified.

Names of flags should be namespaced. Those same constants have very generic names; that will cause problems if the app declares any other symbols with names like "Comments" or
"Multiline". Like your classnames, the constants should have an "ICU" prefix — "ICUCaseInsensitiveMatching", etc.

Below is a patch that fixes these. (I haven't yet had a chance to test it besides just checking that the little test app didn't crash.)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/source/ICUPattern.h

    r10 r17  
    1414 * flags. see http://icu.sourceforge.net/apiref/icu4c/uregex_8h.html#874989dfec4cbeb6baf4d1a51cb529ae 
    1515 */ 
    16 extern unsigned CaseInsensitiveMatching; 
    17 extern unsigned Comments; 
    18 extern unsigned DotMatchesAll; 
    19 extern unsigned Multiline; 
    20 extern unsigned UnicodeWordBoundaries; 
     16extern const unsigned ICUCaseInsensitiveMatching; 
     17extern const unsigned ICUComments; 
     18extern const unsigned ICUDotMatchesAll; 
     19extern const unsigned ICUMultiline; 
     20extern const unsigned ICUUnicodeWordBoundaries; 
    2121 
    2222/*! 
  • trunk/source/ICUPattern.m

    r16 r17  
    2929#import <unicode/ustring.h> 
    3030 
    31 unsigned CaseInsensitiveMatching = UREGEX_CASE_INSENSITIVE; 
    32 unsigned Comments = UREGEX_COMMENTS; 
    33 unsigned DotMatchesAll = UREGEX_DOTALL; 
    34 unsigned Multiline = UREGEX_MULTILINE; 
    35 unsigned UnicodeWordBoundaries = UREGEX_UWORD; 
     31unsigned const ICUCaseInsensitiveMatching = UREGEX_CASE_INSENSITIVE; 
     32unsigned const ICUComments = UREGEX_COMMENTS; 
     33unsigned const ICUDotMatchesAll = UREGEX_DOTALL; 
     34unsigned const ICUMultiline = UREGEX_MULTILINE; 
     35unsigned const ICUUnicodeWordBoundaries = UREGEX_UWORD; 
    3636 
    3737@interface ICUPattern (Private) 
     
    3939-(unsigned)flags; 
    4040-(UChar *)textToSearch; 
    41 -(void)setTextToSearch:(UChar *)utf16String; 
    4241 
    4342@end 
     
    8584                free(re); 
    8685 
    87         [stringToSearch release]; 
     86        if(textToSearch != NULL) 
     87                free(textToSearch); 
    8888        [super dealloc]; 
    8989} 
     
    9494 
    9595-(void)setStringToSearch:(NSString *)aStringToSearchOver { 
    96         if(stringToSearch != nil) 
    97                 [stringToSearch release]; 
    98  
    99         stringToSearch = [aStringToSearchOver retain]; 
    100  
    101         [self setTextToSearch:[aStringToSearchOver UTF16String]]; 
    102 
    103  
    104 -(void)setTextToSearch:(UChar *)utf16String { 
     96        NSParameterAssert(aStringToSearchOver); 
     97        UChar *utf16String = [aStringToSearchOver copyUTF16String]; 
    10598        UErrorCode status = 0; 
    10699 
     
    109102        [self reset]; 
    110103 
    111         textToSearch = utf16String; // retained by the NSString  
    112          
    113104        if(U_FAILURE(status)) { 
    114                 textToSearch = NULL
     105                free(utf16String)
    115106                [NSException raise:@"Invalid String Exception" 
    116107                                        format:@"Could not set text to match against: %s", u_errorName(status)]; 
    117108        } 
     109 
     110        if(textToSearch) 
     111                free(textToSearch); 
     112        textToSearch = utf16String; 
    118113} 
    119114 
     
    187182-(NSArray *)componentsSplitFromString:(NSString *)stringToSplit 
    188183{ 
    189         [self setTextToSearch:[stringToSplit UTF16String]]; 
     184        [self setStringToSearch:stringToSplit]; 
    190185        BOOL isDone = NO; 
    191186        UErrorCode status = 0; 
  • trunk/source/NSStringICUAdditions.h

    r16 r17  
    1616+(NSString *)stringWithICUString:(void *)utf16EncodedString; 
    1717-(void *)UTF16String; 
     18-(void *)copyUTF16String; 
    1819 
    1920-(NSArray *)findPattern:(NSString *)aRegex; 
  • trunk/source/NSStringICUAdditions.m

    r16 r17  
    8686} 
    8787 
     88-(void *)copyUTF16String { 
     89        unsigned int length = [self length]; 
     90        UChar *utf16String = malloc((length+1)*sizeof(UChar)); 
     91        [self getCharacters: utf16String]; 
     92        utf16String[length] = 0; 
     93        return utf16String; 
     94} 
     95 
    8896@end