mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
`Token` and `Span` both represent `start` and `end` as `u32`.
This limits size of source which can be parsed to `u32::MAX`.
19577709db/crates/oxc_span/src/span.rs (L14-L20)
However, this constraint is currently not enforced.
In a release build, code will not panic on arithmetic overflow, so
`start`/`end` could wrap around back to zero if source is 4 GiB or more.
That'd produce nonsense spans. But worse, the lexer relies in some
places on `self.current.token.start` being correct, so if the value
wrapped around, possibly it'd keep rewinding to the start of the source
and lexing it again, causing an infinite loop.
In worst case, if for some reason an application's public API used OXC's
parser with user-supplied source code (parser-as-a-service!), this could
be exploited for denial of service.
This PR adds an assertion to catch this at the start of parsing instead.
This does add an extra instruction, but I imagine the effect will be
negligible compared to the work required to parse the code.
338 lines
12 KiB
Rust
338 lines
12 KiB
Rust
use oxc_diagnostics::{
|
|
miette::{self, Diagnostic},
|
|
thiserror::{self, Error},
|
|
};
|
|
use oxc_span::Span;
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Source length exceeds 4 GiB limit")]
|
|
#[diagnostic()]
|
|
pub struct OverlongSource;
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Flow is not supported")]
|
|
#[diagnostic()]
|
|
pub struct Flow(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Unexpected token")]
|
|
#[diagnostic()]
|
|
pub struct UnexpectedToken(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Expected `{0}` but found `{1}`")]
|
|
#[diagnostic()]
|
|
pub struct ExpectToken(pub &'static str, pub &'static str, #[label("`{0}` expected")] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Invalid escape sequence")]
|
|
pub struct InvalidEscapeSequence(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Invalid Unicode escape sequence")]
|
|
pub struct UnicodeEscapeSequence(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Invalid Character `{0}`")]
|
|
pub struct InvalidCharacter(pub char, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Invalid characters after number")]
|
|
pub struct InvalidNumberEnd(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Unterminated multiline comment")]
|
|
pub struct UnterminatedMultiLineComment(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Unterminated string")]
|
|
pub struct UnterminatedString(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Unexpected flag {0} in regular expression literal")]
|
|
pub struct RegExpFlag(pub char, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Flag {0} is mentioned twice in regular expression literal")]
|
|
pub struct RegExpFlagTwice(pub char, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Unexpected end of file")]
|
|
pub struct UnexpectedEnd(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Unterminated regular expression")]
|
|
pub struct UnterminatedRegExp(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Invalid Number {0}")]
|
|
pub struct InvalidNumber(pub &'static str, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Keywords cannot contain escape characters")]
|
|
#[diagnostic()]
|
|
pub struct EscapedKeyword(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Expected a semicolon or an implicit semicolon after a statement, but found none")]
|
|
#[diagnostic(help("Try insert a semicolon here"))]
|
|
pub struct AutoSemicolonInsertion(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Line terminator not permitted before arrow")]
|
|
#[diagnostic()]
|
|
pub struct LineterminatorBeforeArrow(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Missing initializer in destructuring declaration")]
|
|
#[diagnostic()]
|
|
pub struct InvalidDestrucuringDeclaration(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Missing initializer in const declaration")]
|
|
#[diagnostic()]
|
|
pub struct MissinginitializerInConst(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Lexical declaration cannot appear in a single-statement context")]
|
|
#[diagnostic(help("Wrap this declaration in a block statement"))]
|
|
pub struct LexicalDeclarationSingleStatement(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Async functions can only be declared at the top level or inside a block")]
|
|
#[diagnostic()]
|
|
pub struct AsyncFunctionDeclaration(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Generators can only be declared at the top level or inside a block")]
|
|
#[diagnostic()]
|
|
pub struct GeneratorFunctionDeclaration(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("`await` is only allowed within async functions and at the top levels of modules")]
|
|
#[diagnostic()]
|
|
pub struct AwaitExpression(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("A 'yield' expression is only allowed in a generator body.")]
|
|
#[diagnostic()]
|
|
pub struct YieldExpression(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Invalid class declaration")]
|
|
#[diagnostic(help("Classes can only be declared at top level or inside a block"))]
|
|
pub struct ClassDeclaration(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("A rest element must be last in a destructuring pattern")]
|
|
#[diagnostic()]
|
|
pub struct RestElementLast(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("A rest parameter must be last in a parameter list")]
|
|
#[diagnostic()]
|
|
pub struct RestParameterLast(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Spread must be last element")]
|
|
#[diagnostic()]
|
|
pub struct SpreadLastElement(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Unexpected trailing comma after rest element")]
|
|
#[diagnostic()]
|
|
pub struct RestElementTrailingComma(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Invalid rest element")]
|
|
#[diagnostic(help("Expected identifier in rest element"))]
|
|
pub struct InvalidRestElement(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Cannot assign to this expression")]
|
|
#[diagnostic()]
|
|
pub struct InvalidAssignment(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Optional chaining cannot appear in the callee of new expressions")]
|
|
#[diagnostic()]
|
|
pub struct NewOptionalChain(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("The left-hand side of a `for...of` statement may not be `async`")]
|
|
#[diagnostic()]
|
|
pub struct ForLoopAsyncOf(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("await can only be used in conjunction with `for...of` statements")]
|
|
#[diagnostic()]
|
|
pub struct ForAwait(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Cannot use new with dynamic import")]
|
|
#[diagnostic()]
|
|
pub struct NewDynamicImport(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Classes can't have an element named '#constructor'")]
|
|
#[diagnostic()]
|
|
pub struct PrivateNameConstructor(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Classes may not have a static property named prototype")]
|
|
#[diagnostic()]
|
|
pub struct StaticPrototype(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Constructor can't have get/set modifier")]
|
|
#[diagnostic()]
|
|
pub struct ConstructorGetterSetter(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Constructor can't be an async method")]
|
|
#[diagnostic()]
|
|
pub struct ConstructorAsync(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Cannot use `{0}` as an identifier in an async context")]
|
|
#[diagnostic()]
|
|
pub struct IdentifierAsync(pub &'static str, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Cannot use `{0}` as an identifier in a generator context")]
|
|
#[diagnostic()]
|
|
pub struct IdentifierGenerator(pub &'static str, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Constructor can't be a generator")]
|
|
#[diagnostic()]
|
|
pub struct ConstructorGenerator(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Classes can't have a field named 'constructor'")]
|
|
#[diagnostic()]
|
|
pub struct FieldConstructor(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("An export name cannot include a unicode lone surrogate")]
|
|
#[diagnostic()]
|
|
pub struct ExportLoneSurrogate(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("A string literal cannot be used as an exported binding without `from`")]
|
|
#[diagnostic(help("Did you mean `export {{ {0} as {1} }} from 'some-module'`?"))]
|
|
pub struct ExportNamedString(pub String, pub String, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("A reserved word cannot be used as an exported binding without `from`")]
|
|
#[diagnostic(help("Did you mean `export {{ {0} as {1} }} from 'some-module'`?"))]
|
|
pub struct ExportReservedWord(pub String, pub String, #[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Bad escape sequence in untagged template literal")]
|
|
#[diagnostic()]
|
|
pub struct TemplateLiteral(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Empty parenthesized expression")]
|
|
#[diagnostic()]
|
|
pub struct EmptyParenthesizedExpression(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Illegal newline after {0}")]
|
|
#[diagnostic()]
|
|
pub struct IllegalNewline(
|
|
pub &'static str,
|
|
#[label("{0} starts here")] pub Span,
|
|
#[label("A newline is not expected here")] pub Span,
|
|
);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Tagged template expressions are not permitted in an optional chain")]
|
|
#[diagnostic()]
|
|
pub struct OptionalChainTaggedTemplate(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("A 'get' accessor must not have any formal parameters.")]
|
|
#[diagnostic()]
|
|
pub struct GetterParameters(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("A 'set' accessor must have exactly one parameter.")]
|
|
#[diagnostic()]
|
|
pub struct SetterParameters(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("TS2681: A constructor cannot have a `this` parameter.")]
|
|
#[diagnostic()]
|
|
pub struct TSConstructorThisParameter(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("TS2730: An arrow function cannot have a `this` parameter.")]
|
|
#[diagnostic()]
|
|
pub struct TSArrowFunctionThisParameter(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("'super' can only be used with function calls or in property accesses")]
|
|
#[diagnostic(help("replace with `super()` or `super.prop` or `super[prop]`"))]
|
|
pub struct UnexpectedSuper(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Expected function name")]
|
|
#[diagnostic(help("Function name is required in function declaration or named export"))]
|
|
pub struct ExpectFunctionName(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Missing catch or finally clause")]
|
|
#[diagnostic()]
|
|
pub struct ExpectCatchFinally(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("TS1095: A 'set' accessor cannot have a return type annotation")]
|
|
#[diagnostic()]
|
|
pub struct ASetAccessorCannotHaveAReturnTypeAnnotation(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("TS1108: A 'return' statement can only be used within a function body")]
|
|
#[diagnostic()]
|
|
pub struct ReturnStatementOnlyInFunctionBody(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("TS18007: JSX expressions may not use the comma operator.")]
|
|
#[diagnostic(help("Did you mean to write an array?"))]
|
|
pub struct JSXExpressionsMayNotUseTheCommaOperator(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Line terminator not permitted before using declaration.")]
|
|
#[diagnostic()]
|
|
pub struct LineTerminatorBeforeUsingDeclaration(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Await is not allowed in using declarations.")]
|
|
#[diagnostic()]
|
|
pub struct AwaitInUsingDeclaration(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Using declarations may not have binding patterns.")]
|
|
#[diagnostic()]
|
|
pub struct InvalidIdentifierInUsingDeclaration(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("The left-hand side of a for...in statement cannot be an await using declaration.")]
|
|
#[diagnostic()]
|
|
pub struct AwaitUsingDeclarationNotAllowedInForInStatement(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("The left-hand side of a for...in statement cannot be an using declaration.")]
|
|
#[diagnostic()]
|
|
pub struct UsingDeclarationNotAllowedInForInStatement(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("Using declarations must have an initializer.")]
|
|
#[diagnostic()]
|
|
pub struct UsingDeclarationsMustBeInitialized(#[label] pub Span);
|
|
|
|
#[derive(Debug, Error, Diagnostic)]
|
|
#[error("TS1089: `static` modifier cannot appear on a constructor declaration.")]
|
|
#[diagnostic()]
|
|
pub struct StaticConstructor(#[label] pub Span);
|