Skip to content

Commit 888337a

Browse files
authored
fix: should not panic when SRI options is invalid (#12259)
1 parent 7763043 commit 888337a

File tree

5 files changed

+84
-34
lines changed

5 files changed

+84
-34
lines changed

crates/rspack_binding_api/src/raw_options/raw_builtins/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ use rspack_plugin_runtime::{
9292
use rspack_plugin_runtime_chunk::RuntimeChunkPlugin;
9393
use rspack_plugin_schemes::{DataUriPlugin, FileUriPlugin};
9494
use rspack_plugin_size_limits::SizeLimitsPlugin;
95-
use rspack_plugin_sri::SubresourceIntegrityPlugin;
95+
use rspack_plugin_sri::{SubresourceIntegrityPlugin, SubresourceIntegrityPluginOptions};
9696
use rspack_plugin_swc_js_minimizer::SwcJsMinimizerRspackPlugin;
9797
use rspack_plugin_warn_sensitive_module::WarnCaseSensitiveModulesPlugin;
9898
use rspack_plugin_wasm::{
@@ -819,9 +819,15 @@ impl<'a> BuiltinPlugin<'a> {
819819
}
820820
BuiltinPluginName::SubresourceIntegrityPlugin => {
821821
let raw_options = downcast_into::<RawSubresourceIntegrityPluginOptions>(self.options)
822-
.map_err(|report| napi::Error::from_reason(report.to_string()))?;
823-
let options = raw_options.into();
824-
plugins.push(SubresourceIntegrityPlugin::new(options).boxed());
822+
.and_then(SubresourceIntegrityPluginOptions::try_from);
823+
match raw_options {
824+
Ok(options) => {
825+
plugins.push(SubresourceIntegrityPlugin::new(options, None).boxed());
826+
}
827+
Err(error) => {
828+
plugins.push(SubresourceIntegrityPlugin::new(Default::default(), Some(error)).boxed());
829+
}
830+
}
825831
}
826832
BuiltinPluginName::ModuleInfoHeaderPlugin => {
827833
let verbose = downcast_into::<bool>(self.options)

crates/rspack_binding_api/src/raw_options/raw_builtins/raw_sri.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,22 @@ pub struct RawSubresourceIntegrityPluginOptions {
2222
pub html_plugin: String,
2323
}
2424

25-
impl From<RawSubresourceIntegrityPluginOptions> for SubresourceIntegrityPluginOptions {
26-
fn from(options: RawSubresourceIntegrityPluginOptions) -> Self {
27-
Self {
25+
impl TryFrom<RawSubresourceIntegrityPluginOptions> for SubresourceIntegrityPluginOptions {
26+
type Error = rspack_error::Error;
27+
28+
fn try_from(options: RawSubresourceIntegrityPluginOptions) -> Result<Self, rspack_error::Error> {
29+
let html_plugin = options.html_plugin.try_into()?;
30+
if options.hash_func_names.is_empty() {
31+
return Err(rspack_error::Error::error(
32+
"Expect at least one SRI hash function name.".to_string(),
33+
));
34+
}
35+
let hash_func_names = options
36+
.hash_func_names
37+
.into_iter()
38+
.map(SubresourceIntegrityHashFunction::try_from)
39+
.collect::<Result<Vec<_>, rspack_error::Error>>()?;
40+
Ok(Self {
2841
integrity_callback: if let Some(func) = options.integrity_callback {
2942
Some(Arc::new(move |data| {
3043
let func = func.clone();
@@ -33,13 +46,9 @@ impl From<RawSubresourceIntegrityPluginOptions> for SubresourceIntegrityPluginOp
3346
} else {
3447
None
3548
},
36-
hash_func_names: options
37-
.hash_func_names
38-
.into_iter()
39-
.map(SubresourceIntegrityHashFunction::from)
40-
.collect::<Vec<_>>(),
41-
html_plugin: options.html_plugin.into(),
42-
}
49+
hash_func_names,
50+
html_plugin,
51+
})
4352
}
4453
}
4554

crates/rspack_plugin_sri/src/config.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,30 @@ use crate::integrity::SubresourceIntegrityHashFunction;
1515
pub type IntegrityCallbackFn =
1616
Arc<dyn Fn(IntegrityCallbackData) -> BoxFuture<'static, Result<()>> + Send + Sync>;
1717

18-
#[derive(Debug)]
18+
#[derive(Debug, Default)]
1919
pub enum IntegrityHtmlPlugin {
2020
NativePlugin,
2121
JavaScriptPlugin,
22+
#[default]
2223
Disabled,
2324
}
2425

25-
impl From<String> for IntegrityHtmlPlugin {
26-
fn from(value: String) -> Self {
26+
impl TryFrom<String> for IntegrityHtmlPlugin {
27+
type Error = rspack_error::Error;
28+
29+
fn try_from(value: String) -> Result<Self, rspack_error::Error> {
2730
match value.as_str() {
28-
"JavaScript" => Self::JavaScriptPlugin,
29-
"Native" => Self::NativePlugin,
30-
"Disabled" => Self::Disabled,
31-
_ => panic!("Invalid integrity html plugin: {value}"),
31+
"JavaScript" => Ok(Self::JavaScriptPlugin),
32+
"Native" => Ok(Self::NativePlugin),
33+
"Disabled" => Ok(Self::Disabled),
34+
_ => Err(rspack_error::Error::error(format!(
35+
"Invalid integrity html plugin: {value}"
36+
))),
3237
}
3338
}
3439
}
3540

36-
#[derive(Debug)]
41+
#[derive(Debug, Default)]
3742
pub struct SubresourceIntegrityPluginOptions {
3843
pub hash_func_names: Vec<SubresourceIntegrityHashFunction>,
3944
pub html_plugin: IntegrityHtmlPlugin,

crates/rspack_plugin_sri/src/integrity.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@ pub enum SubresourceIntegrityHashFunction {
1111
Sha512,
1212
}
1313

14-
impl From<String> for SubresourceIntegrityHashFunction {
15-
fn from(s: String) -> Self {
16-
match s.as_str() {
17-
"sha256" => Self::Sha256,
18-
"sha384" => Self::Sha384,
19-
"sha512" => Self::Sha512,
20-
_ => panic!(
21-
"sri hash function only support 'sha256', 'sha384' or 'sha512', but got '{}'.",
22-
s
23-
),
14+
impl TryFrom<String> for SubresourceIntegrityHashFunction {
15+
type Error = rspack_error::Error;
16+
17+
fn try_from(value: String) -> Result<Self, rspack_error::Error> {
18+
match value.as_str() {
19+
"sha256" => Ok(Self::Sha256),
20+
"sha384" => Ok(Self::Sha384),
21+
"sha512" => Ok(Self::Sha512),
22+
_ => Err(rspack_error::Error::error(format!(
23+
"Expect SRI hash function to be 'sha256', 'sha384' or 'sha512', but got '{value}'."
24+
))),
2425
}
2526
}
2627
}

crates/rspack_plugin_sri/src/lib.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,15 @@ static COMPILATION_CONTEXT_MAP: LazyLock<FxDashMap<CompilationId, Arc<SRICompila
4444
#[derive(Debug)]
4545
pub struct SubresourceIntegrityPlugin {
4646
pub options: SubresourceIntegrityPluginOptions,
47+
pub validate_error: Option<rspack_error::Error>,
4748
}
4849

4950
impl SubresourceIntegrityPlugin {
50-
pub fn new(options: SubresourceIntegrityPluginOptions) -> Self {
51-
Self::new_inner(options)
51+
pub fn new(
52+
options: SubresourceIntegrityPluginOptions,
53+
validate_error: Option<rspack_error::Error>,
54+
) -> Self {
55+
Self::new_inner(options, validate_error)
5256
}
5357

5458
pub fn get_compilation_sri_context(id: CompilationId) -> Arc<SRICompilationContext> {
@@ -92,6 +96,23 @@ async fn warn_non_web(
9296
Ok(())
9397
}
9498

99+
#[plugin_hook(CompilerThisCompilation for SubresourceIntegrityPlugin, stage = -10000)]
100+
async fn validate_error(
101+
&self,
102+
compilation: &mut Compilation,
103+
_params: &mut CompilationParams,
104+
) -> Result<()> {
105+
compilation.push_diagnostic(Diagnostic::error(
106+
"SubresourceIntegrity".to_string(),
107+
self
108+
.validate_error
109+
.as_ref()
110+
.expect("should have validate error")
111+
.to_string(),
112+
));
113+
Ok(())
114+
}
115+
95116
#[plugin_hook(CompilerThisCompilation for SubresourceIntegrityPlugin, stage = -10000)]
96117
async fn handle_compilation(
97118
&self,
@@ -156,6 +177,14 @@ impl Plugin for SubresourceIntegrityPlugin {
156177
}
157178

158179
fn apply(&self, ctx: &mut rspack_core::ApplyContext<'_>) -> Result<()> {
180+
if self.validate_error.is_some() {
181+
ctx
182+
.compiler_hooks
183+
.this_compilation
184+
.tap(validate_error::new(self));
185+
return Ok(());
186+
}
187+
159188
if let ChunkLoading::Enable(chunk_loading) = &ctx.compiler_options.output.chunk_loading
160189
&& matches!(
161190
chunk_loading,

0 commit comments

Comments
 (0)