Skip to content

Commit

Permalink
Ensure source buffers are zero-terminated
Browse files Browse the repository at this point in the history
Summary:
Instead of relying on the caller to provide zero-termination, copy
the input source code.

## Changelog:
[Internal]

Reviewed By: neildhar

Differential Revision: D61058835

fbshipit-source-id: 052309cbcb23c8be1ca8fcb80efddaf16571be00
  • Loading branch information
Tzvetan Mikov authored and facebook-github-bot committed Aug 22, 2024
1 parent 73cb666 commit 05d9e75
Showing 1 changed file with 44 additions and 11 deletions.
55 changes: 44 additions & 11 deletions API/hermes/hermes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1197,15 +1197,25 @@ void HermesRuntime::setFatalHandler(void (*handler)(const std::string &)) {
}

namespace {
// A class which adapts a jsi buffer to a Hermes buffer.

/// A class which adapts a jsi buffer to a Hermes buffer.
/// It also provides the ability to create a partial "view" into the buffer.
class BufferAdapter final : public ::hermes::Buffer {
public:
BufferAdapter(std::shared_ptr<const jsi::Buffer> buf) : buf_(std::move(buf)) {
data_ = buf_->data();
size_ = buf_->size();
explicit BufferAdapter(
const std::shared_ptr<const jsi::Buffer> &buf,
const uint8_t *data,
size_t size)
: buf_(buf) {
data_ = data;
size_ = size;
}

explicit BufferAdapter(const std::shared_ptr<const jsi::Buffer> &buf)
: BufferAdapter(buf, buf->data(), buf->size()) {}

private:
/// The buffer we are "adapting".
std::shared_ptr<const jsi::Buffer> buf_;
};
} // namespace
Expand Down Expand Up @@ -1420,6 +1430,28 @@ class HermesPreparedJavaScript final : public jsi::PreparedJavaScript {
}
};

#ifndef HERMESVM_LEAN

/// If the buffer contains an embedded terminating zero, shrink it, so it is
/// one past the size, as per the LLVM MemoryBuffer convention. Otherwise, copy
/// it into a new zero-terminated buffer.
std::unique_ptr<BufferAdapter> ensureZeroTerminated(
const std::shared_ptr<const jsi::Buffer> &buf) {
size_t size = buf->size();
const uint8_t *data = buf->data();

// Check for zero termination
if (size != 0 && data[size - 1] == 0) {
return std::make_unique<BufferAdapter>(buf, data, size - 1);
} else {
// Copy into a zero-terminated instance.
return std::make_unique<BufferAdapter>(std::make_shared<jsi::StringBuffer>(
std::string((const char *)data, size)));
}
}

#endif

} // namespace

std::shared_ptr<const jsi::PreparedJavaScript>
Expand All @@ -1428,11 +1460,10 @@ HermesRuntimeImpl::prepareJavaScriptWithSourceMap(
const std::shared_ptr<const jsi::Buffer> &sourceMapBuf,
std::string sourceURL) {
std::pair<std::unique_ptr<hbc::BCProvider>, std::string> bcErr{};
auto buffer = std::make_unique<BufferAdapter>(jsiBuffer);
vm::RuntimeModuleFlags runtimeFlags{};
runtimeFlags.persistent = true;

bool isBytecode = isHermesBytecode(buffer->data(), buffer->size());
bool isBytecode = isHermesBytecode(jsiBuffer->data(), jsiBuffer->size());
#ifdef HERMESVM_PLATFORM_LOGGING
hermesLog(
"HermesVM", "Prepare JS on %s.", isBytecode ? "bytecode" : "source");
Expand All @@ -1444,18 +1475,17 @@ HermesRuntimeImpl::prepareJavaScriptWithSourceMap(
throw std::logic_error("Source map cannot be specified with bytecode");
}
bcErr = hbc::BCProviderFromBuffer::createBCProviderFromBuffer(
std::move(buffer));
std::make_unique<BufferAdapter>(jsiBuffer));
} else {
#if defined(HERMESVM_LEAN)
bcErr.second = "prepareJavaScript source compilation not supported";
#else
std::unique_ptr<::hermes::SourceMap> sourceMap{};
if (sourceMapBuf) {
auto buf0 = ensureZeroTerminated(sourceMapBuf);
// Convert the buffer into a form the parser needs.
llvh::MemoryBufferRef mbref(
llvh::StringRef(
(const char *)sourceMapBuf->data(), sourceMapBuf->size()),
"");
llvh::StringRef((const char *)buf0->data(), buf0->size()), "");
::hermes::SimpleDiagHandler diag;
::hermes::SourceErrorManager sm;
diag.installInto(sm);
Expand All @@ -1467,7 +1497,10 @@ HermesRuntimeImpl::prepareJavaScriptWithSourceMap(
}
}
bcErr = hbc::BCProviderFromSrc::createBCProviderFromSrc(
std::move(buffer), sourceURL, std::move(sourceMap), compileFlags_);
ensureZeroTerminated(jsiBuffer),
sourceURL,
std::move(sourceMap),
compileFlags_);
#endif
}
if (!bcErr.first) {
Expand Down

0 comments on commit 05d9e75

Please sign in to comment.