-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: load wasm #1705
fix: load wasm #1705
Changes from 5 commits
8daa5bb
74048e2
76dc555
9400f58
49b470e
d9bb9bc
d0aea67
1a31062
24822c4
96c3240
f037029
4511ec6
d9c513d
6b37ba9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,14 @@ | ||
use std::collections::HashMap; | ||
use std::fs::File; | ||
use std::io::Read; | ||
use std::sync::Arc; | ||
|
||
use anyhow; | ||
use wasmparser::{Import, Parser, Payload}; | ||
|
||
use crate::ast::file::{Content, JsContent}; | ||
use crate::compiler::Context; | ||
use crate::plugin::Plugin; | ||
use crate::plugin::{Plugin, PluginLoadParam}; | ||
|
||
pub struct WasmRuntimePlugin {} | ||
|
||
|
@@ -27,4 +32,90 @@ | |
Ok(vec![]) | ||
} | ||
} | ||
|
||
fn load( | ||
&self, | ||
param: &PluginLoadParam, | ||
_context: &Arc<Context>, | ||
) -> anyhow::Result<Option<Content>> { | ||
let file = param.file; | ||
if file.path.to_string_lossy().ends_with(".wasm") { | ||
let final_file_name = format!( | ||
"{}.{}.{}", | ||
file.get_file_stem(), | ||
file.get_content_hash()?, | ||
file.extname | ||
); | ||
_context.emit_assets( | ||
file.pathname.to_string_lossy().to_string(), | ||
final_file_name.clone(), | ||
); | ||
|
||
let mut buffer = Vec::new(); | ||
File::open(&file.path)?.read_to_end(&mut buffer)?; | ||
// Parse wasm file to get imports | ||
let mut wasm_import_object_map: HashMap<&str, Vec<String>> = HashMap::new(); | ||
for payload in Parser::new(0).parse_all(&buffer) { | ||
if let Ok(Payload::ImportSection(imports)) = payload { | ||
for import in imports { | ||
if let Ok(Import { | ||
module, | ||
name, | ||
ty: _, | ||
}) = import | ||
{ | ||
if let Some(import_object) = wasm_import_object_map.get_mut(module) { | ||
import_object.push(name.to_string()); | ||
} else { | ||
wasm_import_object_map.insert(module, vec![name.to_string()]); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 建议添加导入名称的安全验证 当前代码直接使用了WASM模块中的导入名称,但没有进行任何验证,这可能存在安全风险。 建议添加名称验证: + fn is_valid_import_name(name: &str) -> bool {
+ // 只允许字母、数字、下划线和美元符号
+ name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '$')
+ }
if let Ok(Import { module, name, ty: _ }) = import {
+ if !is_valid_import_name(name) {
+ log::warn!("跳过不安全的导入名称: {}", name);
+ continue;
+ }
if let Some(import_object) = wasm_import_object_map.get_mut(module) {
|
||
} | ||
} | ||
} | ||
|
||
let mut module_import_code = String::new(); | ||
let mut wasm_import_object_code = String::new(); | ||
|
||
for (index, (key, value)) in wasm_import_object_map.iter().enumerate() { | ||
module_import_code.push_str(&format!( | ||
"import * as module{module_idx} from \"{module}\";\n", | ||
module_idx = index, | ||
module = key | ||
)); | ||
|
||
wasm_import_object_code.push_str(&format!( | ||
"\"{module}\": {{ {names} }}", | ||
module = key, | ||
names = value | ||
.iter() | ||
.map(|name| format!("\"{}\": module{}[\"{}\"]", name, index, name)) | ||
.collect::<Vec<String>>() | ||
.join(", ") | ||
)); | ||
} | ||
|
||
let mut content = String::new(); | ||
content.push_str(&module_import_code); | ||
|
||
if wasm_import_object_code.is_empty() { | ||
content.push_str(&format!( | ||
"module.exports = require._interopreRequireWasm(exports, \"{}\")", | ||
final_file_name | ||
)); | ||
} else { | ||
content.push_str(&format!( | ||
"module.exports = require._interopreRequireWasm(exports, \"{}\", {{{}}})", | ||
xusd320 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
final_file_name, wasm_import_object_code | ||
)); | ||
} | ||
|
||
return Ok(Some(Content::Js(JsContent { | ||
content, | ||
..Default::default() | ||
}))); | ||
} | ||
|
||
Ok(None) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
/** | ||
*/ | ||
export function greet(): void; | ||
/** | ||
* @param {string} name | ||
*/ | ||
export function greet2(name: string): void; | ||
/** | ||
* @param {number} a | ||
* @param {number} b | ||
* @returns {number} | ||
*/ | ||
export function minus(a: number, b: number): number; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { __wbg_set_wasm } from './index_bg.js'; | ||
import * as wasm from './index_bg.wasm'; | ||
__wbg_set_wasm(wasm); | ||
export * from './index_bg.js'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
let wasm; | ||
export function __wbg_set_wasm(val) { | ||
wasm = val; | ||
} | ||
|
||
const lTextDecoder = | ||
typeof TextDecoder === 'undefined' | ||
? (0, module.require)('util').TextDecoder | ||
: TextDecoder; | ||
|
||
let cachedTextDecoder = new lTextDecoder('utf-8', { | ||
ignoreBOM: true, | ||
fatal: true, | ||
}); | ||
|
||
cachedTextDecoder.decode(); | ||
|
||
let cachedUint8ArrayMemory0 = null; | ||
|
||
function getUint8ArrayMemory0() { | ||
if ( | ||
cachedUint8ArrayMemory0 === null || | ||
cachedUint8ArrayMemory0.byteLength === 0 | ||
) { | ||
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); | ||
} | ||
return cachedUint8ArrayMemory0; | ||
} | ||
xusd320 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
function getStringFromWasm0(ptr, len) { | ||
ptr = ptr >>> 0; | ||
return cachedTextDecoder.decode( | ||
getUint8ArrayMemory0().subarray(ptr, ptr + len), | ||
); | ||
} | ||
/** | ||
*/ | ||
export function greet() { | ||
wasm.greet(); | ||
} | ||
|
||
let WASM_VECTOR_LEN = 0; | ||
|
||
const lTextEncoder = | ||
typeof TextEncoder === 'undefined' | ||
? (0, module.require)('util').TextEncoder | ||
: TextEncoder; | ||
|
||
let cachedTextEncoder = new lTextEncoder('utf-8'); | ||
|
||
const encodeString = | ||
typeof cachedTextEncoder.encodeInto === 'function' | ||
? function (arg, view) { | ||
return cachedTextEncoder.encodeInto(arg, view); | ||
} | ||
: function (arg, view) { | ||
const buf = cachedTextEncoder.encode(arg); | ||
view.set(buf); | ||
return { | ||
read: arg.length, | ||
written: buf.length, | ||
}; | ||
}; | ||
|
||
function passStringToWasm0(arg, malloc, realloc) { | ||
if (realloc === undefined) { | ||
const buf = cachedTextEncoder.encode(arg); | ||
const ptr = malloc(buf.length, 1) >>> 0; | ||
getUint8ArrayMemory0() | ||
.subarray(ptr, ptr + buf.length) | ||
.set(buf); | ||
WASM_VECTOR_LEN = buf.length; | ||
return ptr; | ||
} | ||
|
||
let len = arg.length; | ||
let ptr = malloc(len, 1) >>> 0; | ||
|
||
const mem = getUint8ArrayMemory0(); | ||
|
||
let offset = 0; | ||
|
||
for (; offset < len; offset++) { | ||
const code = arg.charCodeAt(offset); | ||
if (code > 0x7f) break; | ||
mem[ptr + offset] = code; | ||
} | ||
|
||
if (offset !== len) { | ||
if (offset !== 0) { | ||
arg = arg.slice(offset); | ||
} | ||
ptr = realloc(ptr, len, (len = offset + arg.length * 3), 1) >>> 0; | ||
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); | ||
const ret = encodeString(arg, view); | ||
|
||
offset += ret.written; | ||
ptr = realloc(ptr, len, offset, 1) >>> 0; | ||
xusd320 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
WASM_VECTOR_LEN = offset; | ||
return ptr; | ||
} | ||
xusd320 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* @param {string} name | ||
*/ | ||
export function greet2(name) { | ||
const ptr0 = passStringToWasm0( | ||
name, | ||
wasm.__wbindgen_malloc, | ||
wasm.__wbindgen_realloc, | ||
); | ||
const len0 = WASM_VECTOR_LEN; | ||
wasm.greet2(ptr0, len0); | ||
} | ||
|
||
/** | ||
* @param {number} a | ||
* @param {number} b | ||
* @returns {number} | ||
*/ | ||
export function minus(a, b) { | ||
const ret = wasm.minus(a, b); | ||
return ret; | ||
} | ||
|
||
export function __wbg_alert_f837f172b2a24942(arg0, arg1) { | ||
alert(getStringFromWasm0(arg0, arg1)); | ||
} | ||
|
||
export function __wbg_prompt_ec584a06a1c7c28b(arg0, arg1) { | ||
prompt(getStringFromWasm0(arg0, arg1)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* tslint:disable */ | ||
/* eslint-disable */ | ||
export const memory: WebAssembly.Memory; | ||
export function greet2(a: number, b: number): void; | ||
export function minus(a: number, b: number): number; | ||
export function greet(): void; | ||
export function __wbindgen_malloc(a: number, b: number): number; | ||
export function __wbindgen_realloc( | ||
a: number, | ||
b: number, | ||
c: number, | ||
d: number, | ||
): number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
建议更新 wasmparser 依赖版本
当前使用的版本 (0.207.0) 已过时。最新的稳定版本是 0.220.0,建议:
wasmparser = "^0.220.0"
安全检查显示该包没有已知的安全漏洞。
🔗 Analysis chain
建议检查 wasmparser 的版本选择
建议考虑以下几点:
^0.207.0
)来自动接收补丁版本的更新运行以下脚本来验证版本信息:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 439