mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-14 22:29:17 +00:00
fix(parser): avoid panic on escaped string export names (#26146)
## Summary Fix a parser panic when a string-named export decodes to a literal `\u` sequence. Lone-surrogate validation now uses the metadata captured by the lexer instead of rescanning decoded string contents. This also prevents false diagnostics for names such as `"\\uD800"`. ## Before: ``` thread 'main' (10990283) panicked at crates/oxc_ast/src/ast_impl/literal.rs:89:42: end byte index 4 is out of bounds for string of length 0 stack backtrace: 0: __rustc::rust_begin_unwind 1: core::panicking::panic_fmt 2: core::str::slice_error_fail_rt 3: core::str::slice_error_fail 4: <core::ops::range::RangeTo<usize> as core::slice::index::SliceIndex<str>>::index 5: <str as core::ops::index::Index<core::ops::range::RangeTo<usize>>>::index 6: <oxc_ast::ast::literal::StringLiteral>::is_string_well_formed_unicode 7: <oxc_parser::ParserImpl<oxc_parser::config::NoTokensParserConfig>>::parse_module_export_name ```
This commit is contained in:
1 parent
e412cf2ce3
commit
dc09a3aa9d
8 files changed
+17
-24
No files matched your search
@@ -79,22 +79,11 @@ impl Display for NumericLiteral<'_> {
|
||||
|
||||
impl StringLiteral<'_> {
|
||||
/// Static Semantics: `IsStringWellFormedUnicode`
|
||||
/// test for \uD800-\uDFFF
|
||||
///
|
||||
/// See: <https://tc39.es/ecma262/multipage/abstract-operations.html#sec-isstringwellformedunicode>
|
||||
#[inline]
|
||||
pub fn is_string_well_formed_unicode(&self) -> bool {
|
||||
let mut chars = self.value.chars();
|
||||
while let Some(c) = chars.next() {
|
||||
if c == '\\' && chars.next() == Some('u') {
|
||||
let hex = &chars.as_str()[..4];
|
||||
if let Ok(hex) = u32::from_str_radix(hex, 16)
|
||||
&& (0xd800..=0xdfff).contains(&hex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
!self.lone_surrogates
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -971,7 +971,7 @@ impl<'a, C: Config> ParserImpl<'a, C> {
|
||||
let literal = self.parse_literal_string();
|
||||
// ModuleExportName : StringLiteral
|
||||
// It is a Syntax Error if IsStringWellFormedUnicode(the SV of StringLiteral) is false.
|
||||
if literal.lone_surrogates || !literal.is_string_well_formed_unicode() {
|
||||
if !literal.is_string_well_formed_unicode() {
|
||||
self.error(diagnostics::export_lone_surrogate(literal.span));
|
||||
}
|
||||
ModuleExportName::StringLiteral(literal)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
const foo = 1;
|
||||
|
||||
export { foo as "\\u" };
|
||||
export { foo as "\\uD800" };
|
||||
@@ -1,3 +1,3 @@
|
||||
codegen_misc Summary:
|
||||
AST Parsed : 79/79 (100.00%)
|
||||
Positive Passed: 79/79 (100.00%)
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
@@ -1,3 +1,3 @@
|
||||
formatter_misc Summary:
|
||||
AST Parsed : 79/79 (100.00%)
|
||||
Positive Passed: 79/79 (100.00%)
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
@@ -1,6 +1,6 @@
|
||||
parser_misc Summary:
|
||||
AST Parsed : 79/79 (100.00%)
|
||||
Positive Passed: 79/79 (100.00%)
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
Negative Passed: 167/167 (100.00%)
|
||||
|
||||
× Cannot assign to 'arguments' in strict mode
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
semantic_misc Summary:
|
||||
AST Parsed : 79/79 (100.00%)
|
||||
Positive Passed: 75/79 (94.94%)
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 76/80 (95.00%)
|
||||
semantic Error: tasks/coverage/misc/pass/declare-let-private.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["private"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
transformer_misc Summary:
|
||||
AST Parsed : 79/79 (100.00%)
|
||||
Positive Passed: 79/79 (100.00%)
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
Reference in new issue
Block a user