Skip to content

Commit fa0de06

Browse files
committedMay 12, 2019
Avoid setting attributes out of range
1 parent c0fbcf3 commit fa0de06

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed
 

‎Example/Tests/Tests/ZSWStringParserSpec.m

+24
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,30 @@
5757
mockOptions = [OCMockObject mockForClass:[ZSWTaggedStringOptions class]];
5858
});
5959

60+
it(@"should handle a tag with no strings", ^{
61+
ZSWTaggedString *taggedString = [ZSWTaggedString stringWithString:@"<cattail down='true'></cattail>"];
62+
63+
NSArray *tags;
64+
[[mockOptions expect] _private_updateAttributedString:OCMOCK_ANY
65+
updatedWithTags:[OCMArg capture:&tags]];
66+
67+
NSError *error;
68+
69+
id string = [[ZSWStringParser stringWithTaggedString:taggedString
70+
options:mockOptions
71+
returnClass:[NSAttributedString class]
72+
error:&error] string];
73+
74+
expect(string).to.equal(@"");
75+
expect(error).to.beNil();
76+
expect(tags).to.haveCountOf(1);
77+
78+
ZSWStringParserTag *tag = tags.firstObject;
79+
expect(tag.tagName).to.equal(@"cattail");
80+
expect(tag.tagRange.location).to.equal(0);
81+
expect(tag.tagRange.length).to.equal(0);
82+
});
83+
6084
it(@"should handle a string with no tags", ^{
6185
ZSWTaggedString *taggedString = [ZSWTaggedString stringWithString:@"no more timothy hay!"];
6286

‎Example/Tests/Tests/ZSWTaggedStringOptionsSpec.m

+25
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,31 @@
331331

332332
expect(string).to.equal([[NSAttributedString alloc] initWithString:@"santa claus" attributes:nil]);
333333
});
334+
335+
it(@"should handle empty string after tags are removed", ^{
336+
// effectively this is "<blah><null></null></blah>"
337+
ZSWTaggedStringOptions *options = [ZSWTaggedStringOptions optionsWithBaseAttributes:@{
338+
NSFontAttributeName: [UIFont systemFontOfSize:12.0]
339+
}];
340+
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"" attributes:nil];
341+
ZSWStringParserTag *tag1 = [[ZSWStringParserTag alloc] initWithTagName:@"null" startLocation:0];
342+
[tag1 updateWithTag:[[ZSWStringParserTag alloc] initWithTagName:@"/null" startLocation:0]];
343+
344+
ZSWStringParserTag *tag2 = [[ZSWStringParserTag alloc] initWithTagName:@"blah" startLocation:0];
345+
[tag2 updateWithTag:[[ZSWStringParserTag alloc] initWithTagName:@"/blah" startLocation:0]];
346+
347+
[options setDynamicAttributes:^NSDictionary<NSAttributedStringKey,id> * _Nonnull(NSString * _Nonnull tagName, NSDictionary<NSString *,id> * _Nonnull tagAttributes, NSDictionary<NSAttributedStringKey,id> * _Nonnull existingStringAttributes) {
348+
return @{ NSForegroundColorAttributeName: [UIColor redColor] };
349+
} forTagName:@"null"];
350+
351+
[options setAttributes:@{ NSForegroundColorAttributeName: [UIColor redColor] }
352+
forTagName:@"blah"];
353+
354+
[options _private_updateAttributedString:string updatedWithTags:@[ tag1, tag2 ]];
355+
356+
expect(string).to.equal([[NSAttributedString alloc] initWithString:@"" attributes:nil]);
357+
358+
});
334359

335360
describe(@"when a string contains multiple of the same type", ^{
336361
__block ZSWTaggedStringOptions *options;

‎ZSWTaggedString/Classes/ZSWTaggedStringOptions.m

+8
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@ - (void)_private_updateAttributedString:(NSMutableAttributedString *)string
139139
updatedWithTags:(NSArray *)tags {
140140
NSParameterAssert([string isKindOfClass:[NSMutableAttributedString class]]);
141141

142+
if (string.length == 0) {
143+
// For example, a string like '<blah></blah>' has no content, so we can 't
144+
// adjust what's inside based on tags. All we can do is base attributes.
145+
// For dynamic attributes below, we may end up calling out of bounds trying
146+
// to get existing attributes at index 0, which doesn't exist.
147+
return;
148+
}
149+
142150
[string setAttributes:self.baseAttributes range:NSMakeRange(0, string.length)];
143151

144152
ZSWTaggedStringAttribute *unknownTagWrapper = self._private_unknownTagWrapper;

0 commit comments

Comments
 (0)
Please sign in to comment.