ByteArray.toString use-after-free
In this code there is a rare use-after-free case.
The data
pointer obtained from js::GetUint8ArrayLengthAndData()
is volatile, it can become invalid if a GC occurs, because the array buffer may be moved. It seems that in pre-SpiderMonkey 78, the garbage collector would not move these array buffers, and now it does. This causes the pointer to become invalid during JS_NewStringCopyUTF8N()
or JS_NewStringCopyUTF8Z()
if there is a GC right after the string's storage is allocated, but before the string characters are copied, then the string will end up with corrupted data.
This is probably quite unlikely in normal usage but can be triggered reliably by running the test suite with meson test ByteArray --setup=extra_gc
.
Options are:
- Copy the data from the array buffer before passing it to
JS_NewStringCopyUTF8N()
; bad for performance, because it will copy the data twice. - Remove the 'fast path' for byte arrays containing UTF-8 encoded bytes, as it can no longer be properly implemented; also bad for performance because the 'slow path' copies the data twice anyway
- Add API to SpiderMonkey that allows doing this (decoding UTF-8 bytes in an array buffer into a new string) without the possibility of a garbage collection occurring in between.