Files
react-native/ReactCommon
Moti Zilberman 011cf3f884 JSStringToSTLString: truncate string on conversion failure
Summary:
[A recent change to JSStringToSTLString](https://github.com/facebook/react-native/pull/26955) causes a crash when the function is invoked with invalid UTF-16 data. The old behaviour, restored here, was to truncate the string before the first invalid character.

Here's how [the original code](https://github.com/facebook/react-native/blob/aee88b6843cea63d6aa0b5879ad6ef9da4701846/ReactCommon/jsi/JSCRuntime.cpp#L287) handled this case:
```
std::string JSStringToSTLString(JSStringRef str) {
  size_t maxBytes = JSStringGetMaximumUTF8CStringSize(str);
  // ^ maxBytes >= 1 regardless of str's contents
  std::vector<char> buffer(maxBytes);
  // ^ vector is zero initialised
  JSStringGetUTF8CString(str, buffer.data(), maxBytes);
  // ^ writes '\0' at the first invalid character and returns early (see JSC source code)
  return std::string(buffer.data());
  // ^ copies the string up to the first '\0'
}
```

See the JSC implementations of [`JSStringGetUTF8CString`](https://opensource.apple.com/source/JavaScriptCore/JavaScriptCore-7600.8.7/API/JSStringRef.cpp.auto.html) and [`convertUTF16ToUTF8`](https://opensource.apple.com/source/WTF/WTF-7600.7.2/wtf/unicode/UTF8.cpp.auto.html).

Based on the fact that `JSStringGetUTF8CString` *always* null-terminates the buffer - even when it bails out of converting an invalid string - here we're able to both

1. keep the fast path (not zero-initialising, not scanning for the null terminator) for the common case when the data is valid and JSStringGetUTF8CString returns a nonzero length; and
2. return the truncated string when JSStringGetUTF8CString returns an error code of 0, by scanning for the null terminator.

Changelog: [General] [Fixed] - Fix crash when passing invalid UTF-16 data from JSC into native code

Differential Revision: D19902751

fbshipit-source-id: 06bace2719800e921ec115ad6a29251eafd473f6
2020-02-14 12:04:22 -08:00
..