diff --git a/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp b/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp index 1c669181a51..16fcc43d4fa 100644 --- a/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp +++ b/ReactAndroid/src/main/jni/react/jni/JSLoader.cpp @@ -9,14 +9,9 @@ #include #include -#include +#include #include #include -#include -#include -#include -#include -#include #ifdef WITH_FBSYSTRACE #include @@ -28,6 +23,31 @@ using namespace facebook::jni; namespace facebook { namespace react { +class AssetManagerString : public JSBigString { + public: + AssetManagerString(AAsset *asset) : asset_(asset){}; + + virtual ~AssetManagerString() { + AAsset_close(asset_); + } + + bool isAscii() const override { + return false; + } + + const char *c_str() const override { + return (const char *)AAsset_getBuffer(asset_); + } + + // Length of the c_str without the NULL byte. + size_t size() const override { + return AAsset_getLength(asset_); + } + + private: + AAsset *asset_; +}; + __attribute__((visibility("default"))) AAssetManager *extractAssetManager( alias_ref assetManager) { auto env = Environment::current(); @@ -50,17 +70,21 @@ loadScriptFromAssets(AAssetManager *manager, const std::string &assetName) { AASSET_MODE_STREAMING); // Optimized for sequential read: see // AssetManager.java for docs if (asset) { - auto buf = std::make_unique(AAsset_getLength(asset)); - size_t offset = 0; - int readbytes; - while ((readbytes = AAsset_read( - asset, buf->data() + offset, buf->size() - offset)) > 0) { - offset += readbytes; - } - AAsset_close(asset); - if (offset == buf->size()) { - return std::move(buf); + auto script = std::make_unique(asset); + if (script->size() >= sizeof(BundleHeader)) { + // When using bytecode, it's safe for the underlying buffer to not be \0 + // terminated. In all other scenarios, we will force a copy of the + // script to ensure we have a terminator. + const BundleHeader *header = + reinterpret_cast(script->c_str()); + if (parseTypeFromHeader(*header) == ScriptTag::HBCBundle) { + return script; + } } + + auto buf = std::make_unique(script->size()); + memcpy(buf->data(), script->c_str(), script->size()); + return buf; } }