Fix handling of incorrect replacement patterns.

The error code from trying to apply a replacement pattern was not checked,
resulting in a crash inside libicu. This also fixes a few memory leaks
(replacement string objects not correctly autoreleased before returning them
 to the caller).


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@40142 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Niels Grewe 2016-10-12 13:43:32 +00:00
parent 0abb1803ce
commit 6509aeb2de
3 changed files with 79 additions and 2 deletions

View file

@ -1,3 +1,9 @@
2016-10-12 Niels Grewe <niels.grewe@halbordnung.de>
* Source/NSRegularExpression.m: Fix crashes in libicu due to ignored error
codes. Also fix a few memory leaks.
* Tests/base/NSRegularExpression/basic.m: Test cases for this.
2016-10-11 Niels Grewe <niels.grewe@halbordnung.de>
* Source/GSTLS.m

View file

@ -831,6 +831,14 @@ prepareResult(NSRegularExpression *regex,
UTextInitWithNSString(&replacement, template);
output = uregex_replaceAllUText(r, &replacement, NULL, &s);
if (0 != s)
{
uregex_close(r);
utext_close(&replacement);
utext_close(&txt);
DESTROY(ret);
return 0;
}
utext_clone(&ret->txt, output, TRUE, TRUE, &s);
[string setString: ret];
[ret release];
@ -857,13 +865,21 @@ prepareResult(NSRegularExpression *regex,
UTextInitWithNSString(&replacement, template);
output = uregex_replaceAllUText(r, &replacement, NULL, &s);
if (0 != s)
{
uregex_close(r);
utext_close(&replacement);
utext_close(&txt);
DESTROY(ret);
return nil;
}
utext_clone(&ret->txt, output, TRUE, TRUE, &s);
uregex_close(r);
utext_close(&txt);
utext_close(output);
utext_close(&replacement);
return ret;
return AUTORELEASE(ret);
}
- (NSString*) replacementStringForResult: (NSTextCheckingResult*)result
@ -887,13 +903,21 @@ prepareResult(NSRegularExpression *regex,
UTextInitWithNSString(&replacement, template);
output = uregex_replaceFirstUText(r, &replacement, NULL, &s);
if (0 != s)
{
uregex_close(r);
utext_close(&replacement);
utext_close(&txt);
DESTROY(ret);
return nil;
}
utext_clone(&ret->txt, output, TRUE, TRUE, &s);
uregex_close(r);
utext_close(&txt);
utext_close(output);
utext_close(&replacement);
return ret;
return AUTORELEASE(ret);
}
#else
- (NSUInteger) replaceMatchesInString: (NSMutableString*)string

View file

@ -82,6 +82,53 @@ int main()
* which is also the reason for wrapping the previous one in an ARP */
PASS_RUNS([testObj pattern], "Calling -pattern twice runs");
// The pattern does not include a capture group $1, so this should return
// nil;
NSString *replacement = @"should be unset on return";
replacement = [testObj stringByReplacingMatchesInString: @"ab"
options: 0
range: NSMakeRange(0,2)
withTemplate: @"$1c"];
PASS(replacement == nil, "Replacement: returns nil on capture group error");
replacement = [testObj stringByReplacingMatchesInString: @"ab"
options: 0
range: NSMakeRange(0, 2)
withTemplate: @"c"];
PASS_EQUAL(replacement, @"cb", "Replacement correct");
NSString *replMut = [NSMutableString stringWithString: @"ab"];
[testObj replaceMatchesInString: replMut
options: 0
range: NSMakeRange(0,2)
withTemplate: @"$1c"];
PASS_EQUAL(replMut, @"ab",
"Mutable replacement: Incorrect template does not change string");
replMut = [NSMutableString stringWithString: @"ab"];
[testObj replaceMatchesInString: replMut
options: 0
range: NSMakeRange(0,2)
withTemplate: @"c"];
PASS_EQUAL(replMut, @"cb",
"Mutable replacement: Correct replacement for template");
NSTextCheckingResult *r = [testObj firstMatchInString: @"ab"
options: 0
range: NSMakeRange(0,2)];
PASS(r, "Found NSTextCheckingResult");
replacement = @"should be unset on return";
replacement = [testObj replacementStringForResult: r
inString: @"ab"
offset: 0
template: @"$1c"];
PASS(replacement == nil,
"Custom replacement: returns nil on capture group error");
replacement = nil;
replacement = [testObj replacementStringForResult: r
inString: @"ab"
offset: 0
template: @"c"];
PASS_EQUAL(replacement, @"c",
"Custom replacement: Returns correct replacement");
/* To test whether we correctly bail out of processing degenerate patterns,
* we spin up a new thread and evaluate an expression there. The expectation
* is that the thread should terminate within a few seconds.