From 59b40c442009b725d41fe1350f39589b3da6310b Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 10 Jun 2021 13:29:41 -0700 Subject: [PATCH 1/2] Added error handling for very large source files. This situation is now detected earlier so we don't attempt to load the file contents and crash the language server in the process. --- .../pyright-internal/src/analyzer/sourceFile.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/pyright-internal/src/analyzer/sourceFile.ts b/packages/pyright-internal/src/analyzer/sourceFile.ts index 9572fd166502..00f2a2f6ac88 100644 --- a/packages/pyright-internal/src/analyzer/sourceFile.ts +++ b/packages/pyright-internal/src/analyzer/sourceFile.ts @@ -62,8 +62,12 @@ import { SymbolTable } from './symbol'; import { TestWalker } from './testWalker'; import { TypeEvaluator } from './typeEvaluator'; +// Limit the number of import cycles tracked per source file. const _maxImportCyclesPerFile = 4; +// Allow files up to 16MB in length. +const _maxSourceFileSize = 16 * 1024 * 1024; + interface ResolveImportResult { imports: ImportResult[]; builtinsImportResult?: ImportResult; @@ -520,6 +524,15 @@ export class SourceFile { let fileContents = this.getFileContents(); if (fileContents === undefined) { try { + const fileStat = this.fileSystem.statSync(this._filePath); + if (fileStat.size > _maxSourceFileSize) { + this._console.error( + `File length of "${this._filePath}" is ${fileStat.size} ` + + `which exceeds the maximum supported file size of ${_maxSourceFileSize}` + ); + throw new Error('File larger than max'); + } + const startTime = timingStats.readFileTime.totalTime; timingStats.readFileTime.timeOperation(() => { // Read the file's contents. From 0cfe6c1ce28ad0e417675b8eb992bd49ade43aab Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 10 Jun 2021 13:53:27 -0700 Subject: [PATCH 2/2] Moved file length check into timing wrapper so stat check is treated as part of the file read operation. --- .../src/analyzer/sourceFile.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/sourceFile.ts b/packages/pyright-internal/src/analyzer/sourceFile.ts index 00f2a2f6ac88..6e818de53039 100644 --- a/packages/pyright-internal/src/analyzer/sourceFile.ts +++ b/packages/pyright-internal/src/analyzer/sourceFile.ts @@ -524,17 +524,18 @@ export class SourceFile { let fileContents = this.getFileContents(); if (fileContents === undefined) { try { - const fileStat = this.fileSystem.statSync(this._filePath); - if (fileStat.size > _maxSourceFileSize) { - this._console.error( - `File length of "${this._filePath}" is ${fileStat.size} ` + - `which exceeds the maximum supported file size of ${_maxSourceFileSize}` - ); - throw new Error('File larger than max'); - } - const startTime = timingStats.readFileTime.totalTime; timingStats.readFileTime.timeOperation(() => { + // Check the file's length before attempting to read its full contents. + const fileStat = this.fileSystem.statSync(this._filePath); + if (fileStat.size > _maxSourceFileSize) { + this._console.error( + `File length of "${this._filePath}" is ${fileStat.size} ` + + `which exceeds the maximum supported file size of ${_maxSourceFileSize}` + ); + throw new Error('File larger than max'); + } + // Read the file's contents. fileContents = content ?? this.fileSystem.readFileSync(this._filePath, 'utf8');