From 2879a4d42b18e7e9d6bc12119a799c6a8c95e108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sun, 2 Jun 2024 12:35:43 +0900 Subject: [PATCH] fix(es/minifier): Do not index a string with a surrogate pair (#9013) **Related issue:** - Closes #9008 --- crates/swc_ecma_minifier/tests/exec.rs | 5 +++++ .../src/simplify/expr/mod.rs | 20 ++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/swc_ecma_minifier/tests/exec.rs b/crates/swc_ecma_minifier/tests/exec.rs index 8ac36c3f02e1..30ea00ed50b2 100644 --- a/crates/swc_ecma_minifier/tests/exec.rs +++ b/crates/swc_ecma_minifier/tests/exec.rs @@ -11294,6 +11294,11 @@ fn issue_8964() { ); } +#[test] +fn issue_9008() { + run_default_exec_test("console.log('💖'[0]);") +} + #[test] fn issue_8982_1() { run_default_exec_test( diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs index 4823a7c59f53..87ee73f94dd3 100644 --- a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs +++ b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs @@ -159,13 +159,11 @@ impl SimplifyExpr { // 'foo'[1] KnownOp::Index(idx) if (idx as usize) < value.len() => { - self.changed = true; - if idx < 0 { + self.changed = true; *expr = *undefined(*span) - } else { - let value = nth_char(value, idx as _); - + } else if let Some(value) = nth_char(value, idx as _) { + self.changed = true; *expr = Expr::Lit(Lit::Str(Str { raw: None, value: value.into(), @@ -1661,9 +1659,13 @@ where ctx.preserve_effects(span, Expr::Lit(Lit::Bool(Bool { value, span })), orig) } -fn nth_char(s: &str, mut idx: usize) -> Cow { +fn nth_char(s: &str, mut idx: usize) -> Option> { + if s.chars().any(|c| c.len_utf16() > 1) { + return None; + } + if !s.contains("\\ud") && !s.contains("\\uD") { - return Cow::Owned(s.chars().nth(idx).unwrap().to_string()); + return Some(Cow::Owned(s.chars().nth(idx).unwrap().to_string())); } let mut iter = s.chars().peekable(); @@ -1674,7 +1676,7 @@ fn nth_char(s: &str, mut idx: usize) -> Cow { let mut buf = String::new(); buf.push('\\'); buf.extend(iter.take(5)); - return Cow::Owned(buf); + return Some(Cow::Owned(buf)); } else { for _ in 0..5 { iter.next(); @@ -1683,7 +1685,7 @@ fn nth_char(s: &str, mut idx: usize) -> Cow { } if idx == 0 { - return Cow::Owned(c.to_string()); + return Some(Cow::Owned(c.to_string())); } idx -= 1;