LibJS: Tag bytecode cache blobs with program type
Record whether each bytecode cache blob contains a classic script or a module, and pass that type through the serializer call sites. Require validation callers to provide the expected program type so script and module sidecars cannot be reused for the wrong loader.
This commit is contained in:
parent
b327f61ab3
commit
c5b6739c47
4 changed files with 38 additions and 7 deletions
|
|
@ -20,9 +20,9 @@ use crate::{CompiledProgram, CompiledProgramBytecode, ast, u32_from_usize};
|
|||
const MAGIC: &[u8; 8] = b"LBJSBC\0\0";
|
||||
const FORMAT_VERSION: u32 = 1;
|
||||
|
||||
pub fn serialize_compiled_program(compiled: &CompiledProgram) -> Vec<u8> {
|
||||
pub fn serialize_compiled_program(compiled: &CompiledProgram, program_type: ast::ProgramType) -> Vec<u8> {
|
||||
let mut encoder = Encoder::new();
|
||||
CacheBlob { compiled }.encode(&mut encoder);
|
||||
CacheBlob { compiled, program_type }.encode(&mut encoder);
|
||||
encoder.finish()
|
||||
}
|
||||
|
||||
|
|
@ -252,12 +252,14 @@ impl Decode for IgnoredUtf16 {
|
|||
|
||||
struct CacheBlob<'a> {
|
||||
compiled: &'a CompiledProgram,
|
||||
program_type: ast::ProgramType,
|
||||
}
|
||||
|
||||
impl Encode for CacheBlob<'_> {
|
||||
fn encode(&self, encoder: &mut Encoder) {
|
||||
encoder.bytes(MAGIC);
|
||||
FORMAT_VERSION.encode(encoder);
|
||||
self.program_type.encode(encoder);
|
||||
self.compiled.parsed.has_top_level_await.encode(encoder);
|
||||
self.compiled.parsed.is_strict_mode.encode(encoder);
|
||||
ProgramRecord::from(self.compiled).encode(encoder);
|
||||
|
|
@ -265,15 +267,32 @@ impl Encode for CacheBlob<'_> {
|
|||
}
|
||||
|
||||
impl CacheBlob<'_> {
|
||||
fn decode(decoder: &mut Decoder<'_>) -> Option<()> {
|
||||
fn decode(decoder: &mut Decoder<'_>, expected_program_type: ast::ProgramType) -> Option<()> {
|
||||
decoder.expect_bytes(MAGIC)?;
|
||||
(u32::decode(decoder)? == FORMAT_VERSION).then_some(())?;
|
||||
(ast::ProgramType::decode(decoder)? == expected_program_type).then_some(())?;
|
||||
bool::decode(decoder)?;
|
||||
bool::decode(decoder)?;
|
||||
ProgramRecord::decode(decoder)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode for ast::ProgramType {
|
||||
fn encode(&self, encoder: &mut Encoder) {
|
||||
(*self as u8).encode(encoder);
|
||||
}
|
||||
}
|
||||
|
||||
impl Decode for ast::ProgramType {
|
||||
fn decode(decoder: &mut Decoder<'_>) -> Option<Self> {
|
||||
match u8::decode(decoder)? {
|
||||
0 => Some(Self::Script),
|
||||
1 => Some(Self::Module),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ProgramRecord<'a> {
|
||||
kind: ProgramKind,
|
||||
executable: ExecutableRecord<'a>,
|
||||
|
|
|
|||
|
|
@ -704,6 +704,7 @@ pub unsafe extern "C" fn rust_free_compiled_program(compiled: *mut CompiledProgr
|
|||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn rust_serialize_compiled_program_for_bytecode_cache(
|
||||
compiled: *const CompiledProgram,
|
||||
program_type: u8,
|
||||
) -> BytecodeCacheBlob {
|
||||
unsafe {
|
||||
abort_on_panic(|| {
|
||||
|
|
@ -714,7 +715,18 @@ pub unsafe extern "C" fn rust_serialize_compiled_program_for_bytecode_cache(
|
|||
};
|
||||
}
|
||||
|
||||
let bytes = bytecode_cache::serialize_compiled_program(&*compiled);
|
||||
let program_type = match program_type {
|
||||
0 => ast::ProgramType::Script,
|
||||
1 => ast::ProgramType::Module,
|
||||
_ => {
|
||||
return BytecodeCacheBlob {
|
||||
data: std::ptr::null_mut(),
|
||||
length: 0,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let bytes = bytecode_cache::serialize_compiled_program(&*compiled, program_type);
|
||||
let length = bytes.len();
|
||||
let mut bytes = bytes.into_boxed_slice();
|
||||
let data = bytes.as_mut_ptr();
|
||||
|
|
|
|||
|
|
@ -386,9 +386,9 @@ void free_compiled_program(CompiledProgram* compiled)
|
|||
rust_free_compiled_program(compiled);
|
||||
}
|
||||
|
||||
ByteBuffer serialize_compiled_program_for_bytecode_cache(CompiledProgram const& compiled)
|
||||
ByteBuffer serialize_compiled_program_for_bytecode_cache(CompiledProgram const& compiled, ProgramType type)
|
||||
{
|
||||
auto blob = rust_serialize_compiled_program_for_bytecode_cache(&compiled);
|
||||
auto blob = rust_serialize_compiled_program_for_bytecode_cache(&compiled, static_cast<u8>(type));
|
||||
if (!blob.data || blob.length == 0)
|
||||
return {};
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ JS_API void free_parsed_program(FFI::ParsedProgram*);
|
|||
JS_API void free_compiled_program(FFI::CompiledProgram*);
|
||||
|
||||
// Serialize a fully compiled program into a versioned bytecode cache blob.
|
||||
JS_API ByteBuffer serialize_compiled_program_for_bytecode_cache(FFI::CompiledProgram const&);
|
||||
JS_API ByteBuffer serialize_compiled_program_for_bytecode_cache(FFI::CompiledProgram const&, ProgramType);
|
||||
|
||||
// Compile a previously parsed script. Must be called on the main thread.
|
||||
// Consumes and frees the Rust ParsedProgram.
|
||||
|
|
|
|||
Loading…
Reference in a new issue