It's the combination of captures and code blocks. Each time the regex engine is about to execute a code block, it saves the indices of all the captures done so far, so they can be restored at the end. It does this on the pessimistic assumption that code within the block can do anything, including recursively executing the same regex again, overwriting the existing capture indices.
This is why quadratic memory behaviour is being seen.
Not ideal, but can avoided if you use non-capturing braces.
Dave.