As ends and buffer are separately stored, their relative positions can significantly drift away when a lot of strings are interned.
To fix this, their memory should be manually managed as a single growable allocation with two sections (for ends and contents).
This requires a rewrite and likely unsafe code but it would also fix this issue and remove the need to read from both pointers (instead it would be just one).