From 2bc516258bc38ceb1023bfc2d48193792e3082be Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:15:58 -0700 Subject: [PATCH 1/2] Add crashing test --- tests/cases/compiler/parseUnmatchedTypeAssertion.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/cases/compiler/parseUnmatchedTypeAssertion.ts diff --git a/tests/cases/compiler/parseUnmatchedTypeAssertion.ts b/tests/cases/compiler/parseUnmatchedTypeAssertion.ts new file mode 100644 index 0000000000000..8247772f3c9a7 --- /dev/null +++ b/tests/cases/compiler/parseUnmatchedTypeAssertion.ts @@ -0,0 +1 @@ +@<[[import(obju2c77, From 0e2058d2265f40d64a2770c9e4efc0a47d653e3c Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 14 Aug 2023 20:45:13 -0700 Subject: [PATCH 2/2] Prevent detached diagnostics from running off the end of the file --- src/compiler/parser.ts | 12 +++++------ src/compiler/utilities.ts | 21 ++++++++++--------- .../parseUnmatchedTypeAssertion.errors.txt | 21 +++++++++++++++++++ .../reference/parseUnmatchedTypeAssertion.js | 8 +++++++ .../parseUnmatchedTypeAssertion.symbols | 6 ++++++ .../parseUnmatchedTypeAssertion.types | 9 ++++++++ 6 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/parseUnmatchedTypeAssertion.errors.txt create mode 100644 tests/baselines/reference/parseUnmatchedTypeAssertion.js create mode 100644 tests/baselines/reference/parseUnmatchedTypeAssertion.symbols create mode 100644 tests/baselines/reference/parseUnmatchedTypeAssertion.types diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bd8081d1267a1..103a1b08fa837 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1803,7 +1803,7 @@ namespace Parser { return sourceFile; function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) { - parseDiagnostics.push(createDetachedDiagnostic(fileName, pos, end, diagnostic)); + parseDiagnostics.push(createDetachedDiagnostic(fileName, sourceText, pos, end, diagnostic)); } } @@ -2118,7 +2118,7 @@ namespace Parser { const lastError = lastOrUndefined(parseDiagnostics); let result: DiagnosticWithDetachedLocation | undefined; if (!lastError || start !== lastError.start) { - result = createDetachedDiagnostic(fileName, start, length, message, ...args); + result = createDetachedDiagnostic(fileName, sourceText, start, length, message, ...args); parseDiagnostics.push(result); } @@ -2470,7 +2470,7 @@ namespace Parser { if (lastError) { addRelatedInfo( lastError, - createDetachedDiagnostic(fileName, openPosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, tokenToString(openKind), tokenToString(closeKind)) + createDetachedDiagnostic(fileName, sourceText, openPosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, tokenToString(openKind), tokenToString(closeKind)) ); } } @@ -4486,7 +4486,7 @@ namespace Parser { if (lastError && lastError.code === Diagnostics._0_expected.code) { addRelatedInfo( lastError, - createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") + createDetachedDiagnostic(fileName, sourceText, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") ); } } @@ -8326,7 +8326,7 @@ namespace Parser { if (lastError && lastError.code === Diagnostics._0_expected.code) { addRelatedInfo( lastError, - createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") + createDetachedDiagnostic(fileName, sourceText, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") ); } } @@ -9429,7 +9429,7 @@ namespace Parser { if (childTypeTag) { const lastError = parseErrorAtCurrentToken(Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags); if (lastError) { - addRelatedInfo(lastError, createDetachedDiagnostic(fileName, 0, 0, Diagnostics.The_tag_was_first_specified_here)); + addRelatedInfo(lastError, createDetachedDiagnostic(fileName, sourceText, 0, 0, Diagnostics.The_tag_was_first_specified_here)); } break; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 75e1f55abc6f6..4eb8cc9d52aeb 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2150,19 +2150,16 @@ export function createDiagnosticForNodeArrayFromMessageChain(sourceFile: SourceF return createFileDiagnosticFromMessageChain(sourceFile, start, nodes.end - start, messageChain, relatedInformation); } -function assertDiagnosticLocation(file: SourceFile | undefined, start: number, length: number) { +function assertDiagnosticLocation(sourceText: string, start: number, length: number) { Debug.assertGreaterThanOrEqual(start, 0); Debug.assertGreaterThanOrEqual(length, 0); - - if (file) { - Debug.assertLessThanOrEqual(start, file.text.length); - Debug.assertLessThanOrEqual(start + length, file.text.length); - } + Debug.assertLessThanOrEqual(start, sourceText.length); + Debug.assertLessThanOrEqual(start + length, sourceText.length); } /** @internal */ export function createFileDiagnosticFromMessageChain(file: SourceFile, start: number, length: number, messageChain: DiagnosticMessageChain, relatedInformation?: DiagnosticRelatedInformation[]): DiagnosticWithLocation { - assertDiagnosticLocation(file, start, length); + assertDiagnosticLocation(file.text, start, length); return { file, start, @@ -8152,8 +8149,12 @@ export function getLocaleSpecificMessage(message: DiagnosticMessage) { } /** @internal */ -export function createDetachedDiagnostic(fileName: string, start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation { - assertDiagnosticLocation(/*file*/ undefined, start, length); +export function createDetachedDiagnostic(fileName: string, sourceText: string, start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation { + if ((start + length) > sourceText.length) { + length = sourceText.length - start; + } + + assertDiagnosticLocation(sourceText, start, length); let text = getLocaleSpecificMessage(message); if (some(args)) { @@ -8222,7 +8223,7 @@ export function attachFileToDiagnostics(diagnostics: DiagnosticWithDetachedLocat /** @internal */ export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation { - assertDiagnosticLocation(file, start, length); + assertDiagnosticLocation(file.text, start, length); let text = getLocaleSpecificMessage(message); diff --git a/tests/baselines/reference/parseUnmatchedTypeAssertion.errors.txt b/tests/baselines/reference/parseUnmatchedTypeAssertion.errors.txt new file mode 100644 index 0000000000000..112a51fb92e93 --- /dev/null +++ b/tests/baselines/reference/parseUnmatchedTypeAssertion.errors.txt @@ -0,0 +1,21 @@ +parseUnmatchedTypeAssertion.ts(1,2): error TS1109: Expression expected. +parseUnmatchedTypeAssertion.ts(1,12): error TS1141: String literal expected. +parseUnmatchedTypeAssertion.ts(1,12): error TS2304: Cannot find name 'obju2c77'. +parseUnmatchedTypeAssertion.ts(1,21): error TS1109: Expression expected. +parseUnmatchedTypeAssertion.ts(2,1): error TS1005: '{' expected. + + +==== parseUnmatchedTypeAssertion.ts (5 errors) ==== + @<[[import(obju2c77, + ~ +!!! error TS1109: Expression expected. + ~~~~~~~~ +!!! error TS1141: String literal expected. + ~~~~~~~~ +!!! error TS2304: Cannot find name 'obju2c77'. + +!!! error TS1109: Expression expected. + + +!!! error TS1005: '{' expected. +!!! related TS1007 parseUnmatchedTypeAssertion.ts:2:1: The parser expected to find a '}' to match the '{' token here. \ No newline at end of file diff --git a/tests/baselines/reference/parseUnmatchedTypeAssertion.js b/tests/baselines/reference/parseUnmatchedTypeAssertion.js new file mode 100644 index 0000000000000..1400afd182e9f --- /dev/null +++ b/tests/baselines/reference/parseUnmatchedTypeAssertion.js @@ -0,0 +1,8 @@ +//// [tests/cases/compiler/parseUnmatchedTypeAssertion.ts] //// + +//// [parseUnmatchedTypeAssertion.ts] +@<[[import(obju2c77, + + +//// [parseUnmatchedTypeAssertion.js] +; diff --git a/tests/baselines/reference/parseUnmatchedTypeAssertion.symbols b/tests/baselines/reference/parseUnmatchedTypeAssertion.symbols new file mode 100644 index 0000000000000..6cd1af0bb28b4 --- /dev/null +++ b/tests/baselines/reference/parseUnmatchedTypeAssertion.symbols @@ -0,0 +1,6 @@ +//// [tests/cases/compiler/parseUnmatchedTypeAssertion.ts] //// + +=== parseUnmatchedTypeAssertion.ts === +@<[[import(obju2c77, +>obju2c77 : Symbol(obju2c77) + diff --git a/tests/baselines/reference/parseUnmatchedTypeAssertion.types b/tests/baselines/reference/parseUnmatchedTypeAssertion.types new file mode 100644 index 0000000000000..764b3105c6244 --- /dev/null +++ b/tests/baselines/reference/parseUnmatchedTypeAssertion.types @@ -0,0 +1,9 @@ +//// [tests/cases/compiler/parseUnmatchedTypeAssertion.ts] //// + +=== parseUnmatchedTypeAssertion.ts === +@<[[import(obju2c77, +> : any +><[[import(obju2c77, : [[any]] + +> : any +