Skip to content

Commit 429a249

Browse files
committed
[[ Bug 18496 ]] Fix memory leak in MCUnicodeWildcardMatch
This patch fixes a memory leak in MCUnicodeWildcardMatch by ensuring text filter objects are correctly deleted. The MCAutoPointer class has had a default copy constructor added and this class is now used in all places MCTextFilters are created and released. The MCTextFilterRelease API has been removed, delete should just be used on the objects instead.
1 parent 148e6a5 commit 429a249

5 files changed

Lines changed: 44 additions & 50 deletions

File tree

docs/notes/bugfix-18496.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Fix memory leak when using filter on unicode strings

libfoundation/include/foundation-auto.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,11 @@ template<typename T> class MCAutoPointer
725725
{
726726
m_ptr = nil;
727727
}
728+
729+
MCAutoPointer(T* value)
730+
: m_ptr(value)
731+
{
732+
}
728733

729734
~MCAutoPointer(void)
730735
{

libfoundation/include/foundation-text.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,10 @@ class MCTextFilter_NormalizeNFC : public MCTextFilter
222222
};
223223

224224

225-
// Utility functions for creating filter chains
225+
// Utility functions for creating filter chains - the returned objects should
226+
// be released by calling 'delete'.
226227
MCTextFilter *MCTextFilterCreate(MCStringRef, MCStringOptions);
227228
MCTextFilter *MCTextFilterCreate(MCDataRef, MCStringEncoding, MCStringOptions);
228229
MCTextFilter *MCTextFilterCreate(const void *, uindex_t, MCStringEncoding, MCStringOptions, bool from_end = false);
229230

230-
// Equivalent to deleting the text filter
231-
void MCTextFilterRelease(MCTextFilter *);
232-
233-
234231
#endif

libfoundation/src/foundation-text.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,3 @@ MCTextFilter* MCTextFilterCreate(const void *p_data, uindex_t p_length, MCString
491491
return t_chain;
492492
}
493493

494-
void MCTextFilterRelease(MCTextFilter *t_chain)
495-
{
496-
delete t_chain;
497-
}

libfoundation/src/foundation-unicode.cpp

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,11 @@ int32_t MCUnicodeCompare(const void *p_first, uindex_t p_first_length, bool p_fi
899899
MCUnicodeCompareOption p_option)
900900
{
901901
// Create the filters
902-
MCTextFilter *t_first_filter = MCTextFilterCreate(p_first, p_first_length, p_first_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
903-
MCTextFilter *t_second_filter = MCTextFilterCreate(p_second, p_second_length, p_second_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
902+
MCAutoPointer<MCTextFilter> t_first_filter =
903+
MCTextFilterCreate(p_first, p_first_length, p_first_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
904+
905+
MCAutoPointer<MCTextFilter> t_second_filter =
906+
MCTextFilterCreate(p_second, p_second_length, p_second_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
904907

905908
while (t_first_filter->HasData() && t_second_filter->HasData())
906909
{
@@ -910,8 +913,6 @@ int32_t MCUnicodeCompare(const void *p_first, uindex_t p_first_length, bool p_fi
910913
t_diff = t_first_filter->GetNextCodepoint() - t_second_filter->GetNextCodepoint();
911914
if (t_diff != 0)
912915
{
913-
MCTextFilterRelease(t_first_filter);
914-
MCTextFilterRelease(t_second_filter);
915916
return t_diff;
916917
}
917918

@@ -922,9 +923,6 @@ int32_t MCUnicodeCompare(const void *p_first, uindex_t p_first_length, bool p_fi
922923
bool t_first_longer = t_first_filter->HasData();
923924
bool t_second_longer = t_second_filter->HasData();
924925

925-
MCTextFilterRelease(t_first_filter);
926-
MCTextFilterRelease(t_second_filter);
927-
928926
if (t_first_longer)
929927
return 1;
930928
else if (t_second_longer)
@@ -1002,8 +1000,11 @@ bool MCUnicodeFirstIndexOf(const void *p_string, uindex_t p_string_length, bool
10021000
}
10031001

10041002
// Create filter chains for the strings being searched
1005-
MCTextFilter* t_string_filter = MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
1006-
MCTextFilter* t_needle_filter = MCTextFilterCreate(p_needle, p_needle_length, p_needle_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
1003+
MCAutoPointer<MCTextFilter> t_string_filter =
1004+
MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
1005+
1006+
MCAutoPointer<MCTextFilter> t_needle_filter =
1007+
MCTextFilterCreate(p_needle, p_needle_length, p_needle_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
10071008

10081009
// We only want the first codepoint of the needle (for now)
10091010
codepoint_t t_needle_start = t_needle_filter->GetNextCodepoint();
@@ -1022,8 +1023,6 @@ bool MCUnicodeFirstIndexOf(const void *p_string, uindex_t p_string_length, bool
10221023
if (t_needle_matched_len == p_needle_length)
10231024
{
10241025
r_index = t_offset;
1025-
MCTextFilterRelease(t_string_filter);
1026-
MCTextFilterRelease(t_needle_filter);
10271026
return true;
10281027
}
10291028
}
@@ -1032,8 +1031,6 @@ bool MCUnicodeFirstIndexOf(const void *p_string, uindex_t p_string_length, bool
10321031
}
10331032

10341033
// No match was found
1035-
MCTextFilterRelease(t_string_filter);
1036-
MCTextFilterRelease(t_needle_filter);
10371034
return false;
10381035
}
10391036

@@ -1054,8 +1051,11 @@ bool MCUnicodeLastIndexOf(const void *p_string, uindex_t p_string_length, bool p
10541051
}
10551052

10561053
// Create filter chains for the strings being searched
1057-
MCTextFilter* t_string_filter = MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
1058-
MCTextFilter* t_needle_filter = MCTextFilterCreate(p_needle, p_needle_length, p_needle_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
1054+
MCAutoPointer<MCTextFilter> t_string_filter =
1055+
MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
1056+
1057+
MCAutoPointer<MCTextFilter> t_needle_filter =
1058+
MCTextFilterCreate(p_needle, p_needle_length, p_needle_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
10591059

10601060
// We only want the last codepoint of the needle (for now)
10611061
codepoint_t t_needle_end = t_needle_filter->GetNextCodepoint();
@@ -1074,8 +1074,6 @@ bool MCUnicodeLastIndexOf(const void *p_string, uindex_t p_string_length, bool p
10741074
if (t_needle_matched_len == p_needle_length)
10751075
{
10761076
r_index = t_offset - t_string_matched_len;
1077-
MCTextFilterRelease(t_string_filter);
1078-
MCTextFilterRelease(t_needle_filter);
10791077
return true;
10801078
}
10811079
}
@@ -1084,8 +1082,6 @@ bool MCUnicodeLastIndexOf(const void *p_string, uindex_t p_string_length, bool p
10841082
}
10851083

10861084
// No match was found
1087-
MCTextFilterRelease(t_string_filter);
1088-
MCTextFilterRelease(t_needle_filter);
10891085
return false;
10901086
}
10911087

@@ -1094,7 +1090,8 @@ bool MCUnicodeFirstIndexOfChar(const unichar_t *p_string, uindex_t p_string_leng
10941090
uindex_t &r_index)
10951091
{
10961092
// Create filter chain for the string being searched
1097-
MCTextFilter* t_string_filter = MCTextFilterCreate(p_string, p_string_length, kMCStringEncodingUTF16, p_option);
1093+
MCAutoPointer<MCTextFilter> t_string_filter =
1094+
MCTextFilterCreate(p_string, p_string_length, kMCStringEncodingUTF16, p_option);
10981095

10991096
// Process the needle codepoint according to the string options.
11001097
// We use NFC for normalization, so all single char unicode strings
@@ -1114,15 +1111,13 @@ bool MCUnicodeFirstIndexOfChar(const unichar_t *p_string, uindex_t p_string_leng
11141111
{
11151112
t_string_filter->MarkText();
11161113
r_index = t_string_filter->GetMarkedLength() - 1;
1117-
MCTextFilterRelease(t_string_filter);
11181114
return true;
11191115
}
11201116

11211117
t_string_filter->AdvanceCursor();
11221118
}
11231119

11241120
// Could not find the character
1125-
MCTextFilterRelease(t_string_filter);
11261121
return false;
11271122
}
11281123

@@ -1131,7 +1126,8 @@ bool MCUnicodeLastIndexOfChar(const unichar_t *p_string, uindex_t p_string_lengt
11311126
uindex_t &r_index)
11321127
{
11331128
// Create filter chain for the string being searched
1134-
MCTextFilter* t_string_filter = MCTextFilterCreate(p_string, p_string_length, kMCStringEncodingUTF16, p_option, true);
1129+
MCAutoPointer<MCTextFilter> t_string_filter =
1130+
MCTextFilterCreate(p_string, p_string_length, kMCStringEncodingUTF16, p_option, true);
11351131

11361132
// Loop until we find the character
11371133
while (t_string_filter->HasData())
@@ -1141,15 +1137,13 @@ bool MCUnicodeLastIndexOfChar(const unichar_t *p_string, uindex_t p_string_lengt
11411137
{
11421138
t_string_filter->MarkText();
11431139
r_index = p_string_length - t_string_filter->GetMarkedLength();
1144-
MCTextFilterRelease(t_string_filter);
11451140
return true;
11461141
}
11471142

11481143
t_string_filter->AdvanceCursor();
11491144
}
11501145

11511146
// Could not find the character
1152-
MCTextFilterRelease(t_string_filter);
11531147
return false;
11541148
}
11551149

@@ -1165,8 +1159,11 @@ void MCUnicodeSharedPrefix(const void *p_string, uindex_t p_string_length, bool
11651159
}
11661160

11671161
// Set up the filter chains for the strings
1168-
MCTextFilter* t_string_filter = MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
1169-
MCTextFilter* t_prefix_filter = MCTextFilterCreate(p_prefix, p_prefix_length, p_prefix_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
1162+
MCAutoPointer<MCTextFilter> t_string_filter =
1163+
MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
1164+
1165+
MCAutoPointer<MCTextFilter> t_prefix_filter =
1166+
MCTextFilterCreate(p_prefix, p_prefix_length, p_prefix_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
11701167

11711168
// Keep looping until the strings no longer match
11721169
while (t_string_filter->GetNextCodepoint() == t_prefix_filter->GetNextCodepoint())
@@ -1197,9 +1194,6 @@ void MCUnicodeSharedPrefix(const void *p_string, uindex_t p_string_length, bool
11971194
// subsequences of normalised runs of combining chars.
11981195
r_len_in_string = t_string_filter->GetMarkedLength() - 1;
11991196
r_len_in_prefix = t_prefix_filter->GetMarkedLength() - 1;
1200-
1201-
MCTextFilterRelease(t_string_filter);
1202-
MCTextFilterRelease(t_prefix_filter);
12031197
}
12041198

12051199
void MCUnicodeSharedSuffix(const void *p_string, uindex_t p_string_length, bool p_string_native,
@@ -1214,8 +1208,10 @@ void MCUnicodeSharedSuffix(const void *p_string, uindex_t p_string_length, bool
12141208
}
12151209

12161210
// Set up the filter chains for the strings
1217-
MCTextFilter* t_string_filter = MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
1218-
MCTextFilter* t_suffix_filter = MCTextFilterCreate(p_suffix, p_suffix_length, p_suffix_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
1211+
MCAutoPointer<MCTextFilter> t_string_filter =
1212+
MCTextFilterCreate(p_string, p_string_length, p_string_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
1213+
MCAutoPointer<MCTextFilter> t_suffix_filter =
1214+
MCTextFilterCreate(p_suffix, p_suffix_length, p_suffix_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option, true);
12191215

12201216
// Keep looping until the strings no longer match
12211217
while (t_string_filter->GetNextCodepoint() == t_suffix_filter->GetNextCodepoint())
@@ -1246,9 +1242,6 @@ void MCUnicodeSharedSuffix(const void *p_string, uindex_t p_string_length, bool
12461242
// subsequences of normalised runs of combining chars.
12471243
r_len_in_string = t_string_filter->GetMarkedLength() - 1;
12481244
r_len_in_suffix = t_suffix_filter->GetMarkedLength() - 1;
1249-
1250-
MCTextFilterRelease(t_string_filter);
1251-
MCTextFilterRelease(t_suffix_filter);
12521245
}
12531246

12541247
bool MCUnicodeFind(const void *p_string, uindex_t p_string_length, bool p_string_native,
@@ -1283,7 +1276,8 @@ bool MCUnicodeFind(const void *p_string, uindex_t p_string_length, bool p_string
12831276
hash_t MCUnicodeHash(const unichar_t *p_string, uindex_t p_string_length, MCUnicodeCompareOption p_option)
12841277
{
12851278
// Create a filter for the string
1286-
MCTextFilter *t_filter = MCTextFilterCreate(p_string, p_string_length, kMCStringEncodingUTF16, p_option);
1279+
MCAutoPointer<MCTextFilter> t_filter =
1280+
MCTextFilterCreate(p_string, p_string_length, kMCStringEncodingUTF16, p_option);
12871281

12881282
// Fowler-Noll-Vo 1a hash function
12891283
if (sizeof(hash_t) == sizeof(uint64_t))
@@ -1308,7 +1302,6 @@ hash_t MCUnicodeHash(const unichar_t *p_string, uindex_t p_string_length, MCUnic
13081302
t_hash *= kPrime;
13091303
}
13101304

1311-
MCTextFilterRelease(t_filter);
13121305
return t_hash;
13131306
}
13141307
else
@@ -1332,8 +1325,7 @@ hash_t MCUnicodeHash(const unichar_t *p_string, uindex_t p_string_length, MCUnic
13321325
t_hash ^= t_char >> 8;
13331326
t_hash *= kPrime;
13341327
}
1335-
1336-
MCTextFilterRelease(t_filter);
1328+
13371329
return t_hash;
13381330
}
13391331
}
@@ -2234,8 +2226,11 @@ bool MCUnicodeCanBreakWordBetween(uinteger_t xc, uinteger_t x, uinteger_t y, uin
22342226
bool MCUnicodeWildcardMatch(const void *source_chars, uindex_t source_length, bool p_source_native, const void *pattern_chars, uindex_t pattern_length, bool p_pattern_native, MCUnicodeCompareOption p_option)
22352227
{
22362228
// Set up the filter chains for the strings
2237-
MCTextFilter *t_source_filter = MCTextFilterCreate(source_chars, source_length, p_source_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
2238-
MCTextFilter *t_pattern_filter = MCTextFilterCreate(pattern_chars, pattern_length, p_pattern_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
2229+
MCAutoPointer<MCTextFilter> t_source_filter;
2230+
t_source_filter = MCTextFilterCreate(source_chars, source_length, p_source_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
2231+
2232+
MCAutoPointer<MCTextFilter> t_pattern_filter;
2233+
t_pattern_filter = MCTextFilterCreate(pattern_chars, pattern_length, p_pattern_native ? kMCStringEncodingNative : kMCStringEncodingUTF16, p_option);
22392234

22402235
codepoint_t t_source_cp, t_pattern_cp;
22412236

0 commit comments

Comments
 (0)