RegExp: fix Symbol.replace() with an inconsistent match object
Previously, the matched string returned by exec() was assumed to be a
substring of the subject at the reported index.
njs_string_get_substitution() converted "index + matched length" to a byte
offset without a bounds check, and the replace loop advanced the end of the
last match by the byte size of the matched string instead of its character
length. As a result the $' expansion read outside the subject, and on a
multibyte subject the result could start in the middle of a UTF-8 sequence.
The fix is to pass the head and tail slices of the subject to
njs_string_get_substitution() and to track the end of the last match as a
character index. The function no longer converts indexes to offsets, so the
out of range conversion is prevented by construction.
This is an extended fix for #1116 pull request on Github.
Reported by Basavaraj S m (basavaraj@digiscrypt.com).