The utext_extract function (below) is documented to handle its nativeStart and nativeLimit parameters as follows: "If the specified index is out of range, it will be pinned to to be within 0 <= index <= textLength". It is supposed to handle nativeStart<0 by pinning it to 0.
This function is implemented using a pointer to a function that depends on the type of text wrapped by the UText. For UChar* text, that function is ucstrTextExtract. However, it has a couple of problems:
It does not actually pin the nativeStart parameter to 0
It does not correctly handle text with start or limit out of (signed) 32-bit range.
The fix is simple (see below), and fixes segfaults when start<0. The call to ucstrTextAccess sets the internal chunkContents and chunkOffset for an appropriate 32-bit accessible chunk of text. However, the code following that call continues to use the abstract text pointer and the original start value, just truncating the latter to 32 bits and not pinning it to 0. Instead it should use the chunk pointer and the chunk offset (the latter is already in 32-bit range and pinned).
Note, this is an old problem, and was already present in ICU 4.2