Return an error from build-wasm if scanner uses unavailable functions

This commit is contained in:
Max Brunsfeld 2024-02-01 22:18:04 -08:00
parent f383b02741
commit e054de4191
7 changed files with 104 additions and 14 deletions

View file

@ -9,6 +9,25 @@ lazy_static! {
static ref ENGINE: Engine = Engine::default();
}
#[test]
fn test_wasm_stdlib_symbols() {
let symbols = tree_sitter::wasm_stdlib_symbols().collect::<Vec<_>>();
assert_eq!(
symbols,
{
let mut symbols = symbols.clone();
symbols.sort();
symbols
},
"symbols aren't sorted"
);
assert!(symbols.contains(&"malloc"));
assert!(symbols.contains(&"free"));
assert!(symbols.contains(&"memset"));
assert!(symbols.contains(&"memcpy"));
}
#[test]
fn test_load_wasm_language() {
allocations::record(|| {

View file

@ -1,7 +1,9 @@
use super::generate::parse_grammar::GrammarJSON;
use anyhow::{Context, Result};
use anyhow::{anyhow, Context, Result};
use std::{fs, path::Path};
use tree_sitter::wasm_stdlib_symbols;
use tree_sitter_loader::Loader;
use wasmparser::Parser;
pub fn load_language_wasm_file(language_dir: &Path) -> Result<(String, Vec<u8>)> {
let grammar_name = get_grammar_name(&language_dir)
@ -46,5 +48,46 @@ pub fn compile_language_to_wasm(
&output_filename,
force_docker,
)?;
// Exit with an error if the external scanner uses symbols from the
// C or C++ standard libraries that aren't available to wasm parsers.
let stdlib_symbols: Vec<_> = wasm_stdlib_symbols().collect();
let builtin_symbols = [
"__indirect_function_table",
"__memory_base",
"__table_base",
"memory",
];
let mut missing_symbols = Vec::new();
let wasm_bytes = fs::read(&output_filename)?;
let parser = Parser::new(0);
for payload in parser.parse_all(&wasm_bytes) {
if let wasmparser::Payload::ImportSection(imports) = payload? {
for import in imports {
let import = import?.name;
if !builtin_symbols.contains(&import) && !stdlib_symbols.contains(&import) {
missing_symbols.push(import);
}
}
}
}
if !missing_symbols.is_empty() {
Err(anyhow!(
concat!(
"This external scanner uses a symbol that isn't available to wasm parsers.\n",
"\n",
"Missing symbols:\n",
" {}\n",
"\n",
"Available symbols:\n",
" {}",
),
missing_symbols.join("\n "),
stdlib_symbols.join("\n ")
))?;
}
Ok(())
}