Here's the issue:
array_item->Assign(); // Omit all parameters to make the var empty without freeing its memory (for performance, in case this RegEx is being used many times in a loop).
[color=red]if (p < pattern_count-1 // i.e. there's at least one more subpattern after this one (if there weren't, making a copy of haystack wouldn't be necessary because overlap can't harm this final assignment).
&& haystack == array_item->Contents(FALSE)) // For more comments, see similar section higher above.
if (mem_to_free = _tcsdup(haystack))
haystack = mem_to_free;[/color]
array_item->Assign(haystack + UTF8PosToTPos(utf8Haystack, this_offset)
, UTF8LenToTLen(utf8Haystack, this_offset, this_offset - this_offset));
This and another block of code like it are based on the code below. The comment in green explains why the code in red is necessary. Note that for the output var itself (below), the var is emptied only if the entire match failed, in which case haystack won't be used. On the other hand, if an array item (above) fails to match, haystack may still be needed if a later array item matches. If the array item which failed to match is also haystack, haystack is deleted prematurely. The fix is to move the code in red to a point above the if..else.
if (captured_pattern_count < 0) // Failed or no match.
output_var.Assign(); // Make the full-pattern substring blank as a further indicator, and for convenience consistency in the script.
else // Greater than 0 (it can't be equal to zero because offset was definitely large enough).
[color=green]// Fix for v1.0.45.07: The following check allow haystack to be the same script-variable as the
// output-var/array. Unless a copy of haystack is made, any subpatterns to be populated after the
// entire-pattern output-var below would be corrupted. In other words, anything that refers to the
// contents of haystack after the output-var has been assigned would otherwise refer to the wrong
// string.[/color] Note that the following isn't done for the get_positions_not_substrings mode higher above
// because that mode never refers to haystack when populating its subpatterns.
if (pattern_count > 1 && haystack == output_var.Contents(FALSE)) // i.e. there are subpatterns to be output afterward, and haystack is the same variable as the output-var that's about to be overwritten below.
if (mem_to_free = _tcsdup(haystack)) // _strdup() is very tiny and basically just calls strlen+malloc+strcpy.
haystack = mem_to_free;
//else due to the extreme rarity of running out of memory AND SIMULTANEOUSLY having output-var match
// haystack, continue on so that at least partial success is achieved (the only thing that will
// be wrong in this case is the subpatterns, if any).
output_var.Assign(haystack + UTF8PosToTPos(utf8Haystack, offset)
, UTF8LenToTLen(utf8Haystack, offset, offset - offset)); // It shouldn't be possible for the full-pattern match's offset to be -1, since if where here, a match on the full pattern was always found.
One minor point: iTmp3 is
assigned, but the source of the assignment has been either corrupted or freed.
iTmp3 := "foobar"
iTmp1 := "#"
RegExMatch( iTmp1, "([-]?\d+)?\.?(\d+)?(#)?", iTmp )
MsgBox %iTmp3% Do you see this text? I don't.